-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AVR: miscompilation, or stack overflow, when running cryptographic code #109000
Comments
We have some history with AVR miscompilations, so just glancing at this issue my priors are that it is more likely than not that this is a bug somewhere in rustc/LLVM. You've included a fair bit of information in here, but there's no reproducer that I can run to observe the bug. Can you provide a program (snippet or link to a repo/example) that demonstrates the bug, and precise instructions on how to compile it and observe the bug? It would be a great help if someone tackling this doesn't need to have any particular hardware on hand in order to observe the bug. |
To add to saethlin's request for a reproducer: An entire repo is often fine as a reproducer for AVR issues, even though it is usually not for other targets. Often the problem is either so vague that further minimization is futile (so it can't be minimized) or so glaring that further minimization is pointless (making it apparent at a glance at the Cargo.toml or something like that). In particular, a full repo can be desired because some common ecosystem dependencies have used unsound code recently and you may have included one of them in your dependency graph, so please check in your Cargo.lock when pushing the repo so I can see what exact versions of crates you resolved. Also, for that repo, please include the exact rustc/cargo build commands you are using to produce this issue, ideally. A file in the repo listing all of them would not be too much detail. |
zipped file: avr-bug.zip $ tree .
.
├── avr-atmega328p.json
├── .cargo
│ └── config.toml
├── Cargo.lock
├── Cargo.toml
├── rust-toolchain.toml
└── src
└── main.rs avr-atmega328p.json {
"arch": "avr",
"atomic-cas": false,
"cpu": "atmega328p",
"data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8",
"eh-frame-header": false,
"exe-suffix": ".elf",
"executables": true,
"late-link-args": {
"gcc": [
"-lgcc"
]
},
"linker": "avr-gcc",
"linker-is-gnu": true,
"llvm-target": "avr-unknown-unknown",
"max-atomic-width": 8,
"no-default-libraries": false,
"pre-link-args": {
"gcc": [
"-mmcu=atmega328p",
"-Wl,--as-needed,--print-memory-usage,--detailed-mem-usage",
"-fpack-struct",
"-fshort-enums",
"-Wstack-usage=20",
"-Wall","-Wextra","-fstack-usage"
]
},
"target-c-int-width": "16",
"target-pointer-width": "16"
} .cargo/config.toml rustflags = ["-Z emit-stack-sizes"]
[target.avr-atmega328p]
runner = "qemu-system-avr -M uno -nographic -serial tcp::5678,server=on -bios"
[build]
target = "avr-atmega328p.json"
[unstable]
build-std = ["core"] Cargo.toml [package]
name = "avr-bug"
version = "0.1.0"
edition = "2021"
[dependencies]
panic-halt = "0.2.0"
ufmt = "0.1.0"
noble-secp256k1 = { git = "https://github.com/xphoniex/noble-secp256k1-rs", default-features = false, features = ["8-bit"] }
hmac-sha256 = { version = "1.1.6", default-features = false, features = ["opt_size"] }
[dependencies.arduino-hal]
git = "https://github.com/rahix/avr-hal"
rev = "4c9c44c314eb061ee20556ef10d45dea36e75ee4"
features = ["arduino-uno"]
[dependencies.avr-device]
version = "0.5.0"
[profile.dev]
panic = "abort"
debug = true
lto = true
opt-level = "s"
[profile.release]
panic = "abort"
codegen-units = 1
debug = true
lto = true
#opt-level = "s"
#opt-level = "z"
opt-level = 2
strip = true
[profile.dev.package.compiler_builtins]
overflow-checks = false rust-toolchain.toml [toolchain]
channel = "nightly"
components = [ "rust-src" ]
profile = "minimal" src/main.rs #![no_std]
#![no_main]
use panic_halt as _;
use arduino_hal::prelude::*;
use core::fmt::Debug;
use ufmt::uWrite;
fn print_hex_arr<S>(tag: &str, serial: &mut S, arr: &[u8])
where
S: uWrite,
<S as uWrite>::Error: Debug,
{
ufmt::uwrite!(serial, "{} = ", tag).unwrap();
for e in arr.iter() {
ufmt::uwrite!(serial, "{:02x}", *e).unwrap();
}
ufmt::uwrite!(serial, "\r\n").unwrap();
}
fn print_hex_arr_rev<S>(tag: &str, serial: &mut S, arr: &[u8])
where
S: uWrite,
<S as uWrite>::Error: Debug,
{
ufmt::uwrite!(serial, "{} = ", tag).unwrap();
for e in arr.iter().rev() {
ufmt::uwrite!(serial, "{:02x}", *e).unwrap();
}
ufmt::uwrite!(serial, "\r\n").unwrap();
}
#[arduino_hal::entry]
fn main() -> ! {
let dp = arduino_hal::Peripherals::take().unwrap();
let pins = arduino_hal::pins!(dp);
let mut serial = arduino_hal::default_serial!(dp, pins, 57600);
/*
// Uncommenting this part changes the output of hmacs
use noble_secp256k1::awint::{cc, inlawi, inlawi_ty, Bits, InlAwi};
use noble_secp256k1::{BigNum, Curve};
let mut private_key = inlawi!(0x02_u512);
let curve = Curve::secp256k1();
let public_key = curve.multiply_simple(&mut private_key);
let mut buf = [0; 32];
public_key.x.to_u8_slice(&mut buf);
print_hex_arr_rev("x", &mut serial, &buf);
public_key.y.to_u8_slice(&mut buf);
print_hex_arr_rev("y", &mut serial, &buf);
*/
let h = hmac_sha256::HMAC::mac(b"hello", b"key");
print_hex_arr(" mac", &mut serial, &h);
let h = hmac_sha256::Hash::hash(b"hello");
print_hex_arr("hash", &mut serial, &h);
loop {}
} $ rustc -vV
rustc 1.69.0-nightly (ef934d9b6 2023-02-08)
binary: rustc
commit-hash: ef934d9b632b8ac00276558824664c104b92b5f0
commit-date: 2023-02-08
host: x86_64-unknown-linux-gnu
release: 1.69.0-nightly
LLVM version: 15.0.7 |
In order to run this you need both avr toolchain such as $ telnet localhost 5678
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
mac = 9307b3b915efb5171ff14d8cb55fbcc798c6c0ef1456d66ded1a6aa723a58b7b
hash = 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 then try changing |
For future reference, creating and pushing a repo to GitHub or another host that I can clone with a single command would have been preferred over something that requires me to manually reconstruct the files inside a repository. |
You're right, added the zip file. |
Hmm. I don't know, in that case! Fair enough?! Thank you for the clear instructions, I will try to reproduce this soon. Also you will want to update to a version of rustc of about February 19 or later, as an ABI fix for AVR targets was merged about then. It doesn't affect your visible source but it may affect your dependencies. |
polite bump. any updates on this? |
The reproducer doesn't reproduce the bug on the latest nightly. At least it doesn't when I try it, I always get the correct output regardless of opt level. If I turn off LTO though, I get
So perhaps we still have a bug but I think the one you meant to report here is fixed? Can you confirm? |
Thanks for the reply. Only half is fixed: After updating to nightly 1.72, this consistently produces the correct output regardless of compiler settings: let h = hmac_sha256::HMAC::mac(b"hello", b"key"); // hmac for input "hello" with key "key"
print_hex_arr(" mac", &mut serial, &h);
let h = hmac_sha256::Hash::hash(b"hello"); // sha256 of "hello"
print_hex_arr("hash", &mut serial, &h); (sidenote: how can I point my cargo to a locally compiled rustc? I can then git bisect and find out what fixed this from 1.62) However if you go back to main.rs, you'll see a code block which is commented out: /*
// Uncommenting this part changes the output of hmacs
use noble_secp256k1::awint::{cc, inlawi, inlawi_ty, Bits, InlAwi};
use noble_secp256k1::{BigNum, Curve};
let mut private_key = inlawi!(0x02_u512);
let curve = Curve::secp256k1();
let public_key = curve.multiply_simple(&mut private_key);
let mut buf = [0; 32];
public_key.x.to_u8_slice(&mut buf);
print_hex_arr_rev("x", &mut serial, &buf);
public_key.y.to_u8_slice(&mut buf);
print_hex_arr_rev("y", &mut serial, &buf);
*/
let h = hmac_sha256::HMAC::mac(b"hello", b"key");
print_hex_arr(" mac", &mut serial, &h);
let h = hmac_sha256::Hash::hash(b"hello");
print_hex_arr("hash", &mut serial, &h); Uncomment it and let's run the code,
But we get:
So, my initial guess what that some weird stack overflow is happening (from the code block we just uncommented) and decided to move the hmac part on top of the code so like:
Here are the outputs I'm getting now:
as you can see, plenty of different variations, depending on just the compiler setting. this might have something to do with overflow, but shouldn't compiler catch it?
|
WG-prioritization assigning priority (Zulip discussion). @xphoniex a note about support of compile target @rustbot label -I-prioritize +P-low |
You probably want to |
This could be another case of compiler_builtins providing its own intrinsics in place of libgcc ones - could you try adding this to build-std-features = ["compiler-builtins-mangled-names"] ... and trying again? |
rustflags = ["-Z emit-stack-sizes"]
build-std-features = ["compiler-builtins-mangled-names"] also tried [unstable]
build-std = ["core"]
build-std-features = ["compiler-builtins-mangled-names"] same output as before. |
This was such a bad idea, started with $ git checkout master
$ git bisect start
$ git bisect good
$ git bisect bad 1.66.0 but it won't compile with unknown print request `split-debuginfo` which I suppose is asked for by decided to start from error: failed to load manifest for workspace member `/github.com/rust-lang/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/src/rust/library/sysroot`
Caused by:
failed to read `/github.com/rust-lang/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/src/rust/library/sysroot/Cargo.toml`
Caused by:
No such file or directory (os error 2) tried and $ git bisect bad
The merge base f058493307813a5298851f79ad6187f4ad2c7e15 is bad.
This means the bug has been fixed between f058493307813a5298851f79ad6187f4ad2c7e15 and [33c3d101280c8eb3cd8af421bfb56a8afcc3881d].
$ git bisect bad
The merge base f058493307813a5298851f79ad6187f4ad2c7e15 is bad.
This means the bug has been fixed between f058493307813a5298851f79ad6187f4ad2c7e15 and [33c3d101280c8eb3cd8af421bfb56a8afcc3881d].
... also tried 1.68 separately, and that doesn't work either, same error as 1.67. |
Okie, I think I got it - your code prints invalid results¹ because you've got a stack overflow 😇 Since AVR doesn't provide memory hardware watches (and rustc/llvm don't insert stack canaries), stack overflow in here doesn't cause the program to halt but rather simply trashes some other stuff present in RAM - in this case, this stuff happens to be apparently some values used to calculate the hashes. We can prove it with simavr - first, let's start the simulator:
... then, in another tab, let's run avr-gcc:
Now, before we're off to detecting stack trashing, we must talk about memory layout - on this AVR, since there's only two kilobytes of RAM, it's pretty straightforward:
When an AVR program starts, it copies "static stuff" from flash memory into RAM² - that stuff ends up at the beginning of the memory; after that, we've got the stack which starts at the end of RAM and grows down (i.e. towards the lower addresses). That is to say, if a program uses 32 bytes of static data, it leaves 2048 - 32 = 2016 bytes for stack frames; any stack frame larger than that will, sooner or later, unavoidably overwrite some random stuff present in RAM. Okie, okie, let's get back to business - let's setup a memory watch to find out what messes up the RAM! After running a single instruction:
... the list of registers at the top gets filled with values - in particular, we're interested in the SP (stack pointer) register:
... and, in-particular in-particular, we're interested in the second value there - (this register has two values because Before we're able to setup the watch, we have to find one more value: size of our "constant stuff" section; to do that we can simply move forward a few instructions, up to an intrinsic called
... where
This means that our stack effectively ends at:
... so let's create a watch precisely for that:
... let the program continue:
... and voilà, our RAM gets corrupted:
... anything after this instruction is effectively undefined behavior (from Rust's point of view, at least). We can even print stacktrace, for fun:
Soooo.... tl;dr he data too big for he god damn RAM. Not all hope is lost, though! -- if you really need to compute those hashes on AVR, I think you could relatively easily use the avr-progmem crate to store those big bois: ... into flash so that they are not copied into RAM (effectively trading-off a bit of performance here). That's just a hunch, but doing that would be my first step - and you could even upstream it later by hiding this avr-progmem behind some feature-flag or (due diligence: I've been testing the program with https://reviews.llvm.org/D152059 and https://reviews.llvm.org/D152063 patches applied; it's possible that the current nightly compiler miscompiles something, but everything seems to be alright with those two patches.) ¹ or sometimes it hangs because (depending on the compiler flags and Moon's alignment) the code panics which causes it to enter the ² that's kinda-sorta required because most AVR instructions don't support reading stuff directly from the flash memory - and so if the program did not do that, each read into the flash memory would require an extra register and an extra instruction which could become wasteful in the long term |
Thanks @Patryk27 for the entire time you dedicated to present this solution. @xphoniex problems of Maybe eventually in future, someone can produce a script to use SIMAVR and GDB to test this case condition automagically. Are we able to close this issue? |
Thanks @Patryk27 for the write up, needed some time to verify this. I can't re-produce this entirely on my side: I don't have
in another terminal:
got me connected. however, I can't see Edit: can see
let's continue anyway:
so my there seems to be an issue with the way you've calculated the height of static data:
IIUC, this loop keeps increasing So the height is
So, the end of our stack is either
but when I create a watch for that:
program outputs:
but I'm not getting this:
manually examining using
-- Edit: watches are hit when using
|
Oh, neat - thanks for answering, I'll re-check my logic today / tomorrow 🙂 |
Thank you for the help. Updated my post.
Former is lighter on CPU, and releases, hence why So this is no longer rust's fault, but still three questions remaining:
Edit: just realized the 484 shown here matches what I calculated in the above post, I can manually set watch points and run the program, but that has to be scripted and run multiple times to pinpoint it. And backtrace doesn't seem to have this info. Any ideas re this? This is the most important thing, as I can estimate how much stack I have left, etc. Another idea would be to re-compile There's japaric/cargo-call-stack, however it doesn't support avr. |
Did some further digging, are you sure about this:
If I understood correctly, static part of memory gets filled on start up (in For example, if I slightly change the code by moving this part inside its own block: {
let h = hmac_sha256::HMAC::mac(b"hello", b"key");
print_hex_arr(" mac", &mut serial, &h);
let h = hmac_sha256::Hash::hash(b"hello");
print_hex_arr("hash", &mut serial, &h);
} and break on the first
which is showing however, when I place a watch right after the end of the static area:
this has grown the static area upwards, whereas I was expecting the static area to remain the same size, but the program stack to grow downwards and overwrite it. how is it possible to still create static stuff after
so either:
|
According to: rust-lang/rust#109000 (comment)'
TLDRI created an DetailAccording to previous requested by @workingjubilee here, I created a git repo with the reproducer based on @xphoniex (issue author) comment. The motivation is because I was not able to compile the code as originally given. @xphoniex I made some small adjustments to the reproducer you have sent which are visible in the repository log history. Please clone this repository and check if you can validate it as an official reproducer for the issue. It's very important that we have a deterministic reproducer that works the same way independent of time or machine it is run. IMPORTANT If you consider the case, update the original issue with a link to this repository. |
Testing in real hardwareTLDR: It has been proved that the problem is not in the rust compiler side. I followed an different approach than @Patryk27 and decided to experiment to take the core effect of the I assumed that the core effect desired by the reproducer boils down to: let h1 = hmac_sha256::HMAC::mac(b"hello", b"key");
let h2 = hmac_sha256::Hash::hash(b"hello"); Then I inserted this two lines into another project that I've being using since a year, that targets the same hardware of the reproducer. It runs on a board with an atmega328p and an lcd display. I defined that the values of variables ResultsTLDR: The result was as expected; The same (and correct) output value no matter what kind of optimization level I use. This video shows the result in real-time, which is as expected as below and independent of the optimization level tested.
I tested for following optimizations levels:
DiscussionAlthough this present test does not answer the question In my code I did not use ufmt dependency. And I do not send the output to the serial, instead I send it direct to the lcd display. But I have settled up in my project a working serial port driver (which is tested in field). I did not use it because I had not a cable in the test moment. But we can conclude that if the issue is about a possible mis-behaviour of the rust compiler, then the test probes that it is not the case. The rust compiler is able to compile a program for AVR target that correct calculates hash functions values and displays its values into a lcd display (and hopefully into a serial port). If there is no problem with the Rust compiler then the reproducer problem should be with some dependency it is using (for example ufmt or serial) and/or with the compiler options it's using (check this compiler correction I've made on reproducer code). It's also important to note that I've found that But if this is the case, then the best forum to discuss I consider that in the community we have a lack of documentation on how to detect stack overflow errors. Even I do not know a consistent method to safely detect this kind of error yet. I was reading @Patryk27 and your (@xphoniex) comment's exchange about that subject, and found that you also had problem to detect the exact point where stack reach its limits. Eventually you may help the community to write some blog post about it. What's nextI think this present hardware test make this issue eligible to be closed, once it has been proved the rust compiler capability to produce the desired effect. Showing therefore that the issue has other cause. But @xphoniex please take your time to check by your own the data presented here and let us know your considerations. |
Thank you Flavio, for putting in the effort.
Can you give me the compiler error you get with the zip file? Remember you have to
So, I went back and tried different toolchains, and to my surprise, I was getting the correct hashes. After downloading the zip file again, and comparing all files one by one, I realized this line had fixed the issue: build-std-features = ["compiler-builtins-mangled-names"] which had been suggested by Patryk here. Funnily enough, when I tried this remedy before, here, it didn't solve the issue for me back then. Right now I can't re-produce it. Anyway, you should be able to reproduce with these settings: # Cargo.toml
opt-level = "s | z"
# rust-toolchain.toml
channel = "nightly-2022-07-10 | nightly-2022-08-11 | nightly-2022-07-10"
So, the original issue with mac/hmac is resolved somewhere in 1.70 - 1.72 but to get it working with prior versions you can use This is in fact a compiler issue, and if someone can point down the commit which has resolved it, I'd be grateful, as I wasn't able to using Why I still kept this issue open?Most of what Patryk wrote is correct expect the way he cacluated the copy size of the static data in Problem now is, I stepped through the code line by line inside gdb, and I can see the stack is growing from both sides:
I don't know why the 2nd is happening, and I've tried talking to a few people with knowledge of AVR but no one's engaged me so far.
I'm not 100% sure this is not a Rust/LLVM issue given the aforementioned points. Let me know what you think. |
First, before anything: Rust will naturally prefer to statically link all crates and do considerable inlining, or recommend such to LLVM, which can make it hard to track things down at the best of times. And the crate you named uses However, it is also very common for tools like So, armed with that knowledge, finding ourselves at the bottom of a very deep and dark rabbit hole, that might be filled with monsters, actually, I must ask: Won't end up showing... where? |
My understanding was that
The |
preface: tried posting this to simavr google group but couldn't, and the gitter room suggested is not very active, it's our own Flavio, and Patryk. How does stack memory grow on AVR? I've coded a small program for atmega328p, in rust/llvm, and it's not giving me the expected output. I don't know if the issue is on the compiler side or memory, so I'm trying to rule out the latter first (stack overflow).
Is everything I said above correct? cause in practice, something else is happening. Initially, In one terminal:
In another:
then keep
and after another 7
I don't know what that
the code being executed (or about to execute?) is what are those did I get the growing direction wrong or is it a rust/llvm bug? |
@xphoniex based on your suggestion here I was able to reproduce the error using an older version of rust compiler ( Which means that the issue is related to particular versions of Rust compiler, and that the same problem does not occurs in recent versions. This has been previously anticipated by @saethlin here when he says:
Certainly one of the causes of this Rust AVR's compiling quality variation, is the fact that there is not any kind of regression tests being performed by the compiler team's development workflow for this target. Which means that in the proccess of development new broken avr compilers may be produced in future, with no alert (and by different reasons other than related to #109000). As @hahix, the author of some dependencies you use in your reference code stated: even if regression tests on AVR would have no effect in terms to interrupt the compiler's development workflow. It would be a great start to have a flag indicating that something has been broken. In this sense, why not close this issue in favor of #107612 ? See also: This @Patryk27's comment here
|
There are two problems in this issue, one is a math problem as you put it, and the other is likely a stack overflow. First one is solved and no longer an issue, but second one is still persisting. In the re-producer zip, But in my previous post, I have demonstrated that even if
is writing values If you have an explanation for this we can close this issue? |
TLDR It seems your new question departs from the topic raised in the original post. I recomend close this and open a new issue.
It seems to me that you probably unintentionally made a topic drift. In other words, for all ways I look at your original post at this moment, there is not a single one where I can realize that your initial questions were not answered. If you agree with above statement and you still want to open a new issue, remember to include complete information:
|
I mean, I didn't deeply analyze the code structure of that crate, but in the general case it is often very respected cross-crate! As I understand it, it causes the Rust compiler to delay code generation in many cases until the final crate, thus making it much more like "true inlining", by forcing codegen to happen "on-the-spot". This also can cause compilation performance regressions, by forcing repeated needless codegen. I agree that we seem to be on to a new topic and the current primary issue seems to be resolved, so I will close this. Even if we are not, it is usually better to initially prefer to split up a nebulous issue rather than assuming two problems are intrinsically connected, so if there are any remaining subissues of this that seem unresolved, please open a new issue for them. |
The issue still existsHere's video evidence to prove it: I was able to produce this after a mere 10 second of playing with the code. This is a telltale that there are deeper problems when it comes to memory, caused by the compiler. I politely ask that you @workingjubilee re-open this issue, and not close it again until it's been fully resolved. All the relevant context, info, and re-producer exists on this issue, so there's no need to re-open another issue and copy/paste the same info there. There is however, a need to not to clutter this space, so that someone with knowledge of llvm/rust can follow along, and maybe eventually help, and resolve this matter. @saethlin I read your post on Zulip, and I understand inactiveness of this issue is your concern. I've provided evidence in prior posts in gdb, and you can see the gif I've attached as evidence that this issue still exists in compiler. Please let me know if you need anything else. It's not inactive because it's solved, it's inactive because no one has responded to the issues I raised. I kindly ask you to make your instance clear and ask @workingjubilee to re-open this issue. This is not a new question, it doesn't depart from original post, and I have clearly stated it in my original post - which is unedited - I'll highlight the relevant parts for you:
"not only that" means I have't even told you the most important part yet. This was the centerpiece of my issue, as calling other fns, even small ones like a debug / print, was corrupting the output. I have posted an example of what I meant by and I have posted the compiler version needed to re-produce this issue, but you seem to have glossed over this info. if my issue was that I was getting incorrect hmac, I would just set |
I read over this issue from front to back in one sitting and I cannot tell whether the issue you're having is still a stack overflow, a miscompilation, an unsound dependency, or a combination of these. You can always link to this issue from a new more targetted one.
I have not found this information, it may have been there, but it wasn't obvious to me either. A new less cluttered issue may be easier to follow.
that's uncalled for and not making people more likely to want to participate in this issue. Consider avoiding such comments in the future. |
@xphoniex There are very few people who understand Rust and LLVM well enough to even try to tackle this issue. There are even fewer who have have made commits to rust-lang/rust specifically to fix issues for AVR and MSP430. I am one of them who has, and I do it because I care a lot about Rust's multi-platform viability. If I am asking you to reorganize the data in a way I prefer, I am not bothered if you say you don't understand why I have a given preference, but it is not some plot to dismiss the issue at hand. It is, rather, part of how I sort and think about issues and how to resolve them. Nonetheless, I have nothing against reopening this issue I suppose, but please trust that my request was not some idle whim. |
Using rust to compile for Arduino target, I'm see a lot of weird and random behaviors from compiler when making changes to profile and compiler setting. (I'm using avr-hal for uno, here's a sample)
As an example, if I use
hmac-sha256
crate:I get different outputs depending on
opt-level
andlto
, correct one is:which I'm getting from
opt-level=2
with bothlto=true
and unspecified, however:not only that, even if I run fns from another crate, even with the working
opt-level = 2
, I get incorrect output:has a wrong output and instead this works:
before I compile a bug report at gcc, I want to make sure the fault is not at rust side. here's the final command that rustc is running to link the final elf:
as you can see it's using
-O1
which I haven't specified anywhere. (See avr-atmega328p.json)I have tried overriding in my avr-atmega328p.json file inside
pre-link-args
but that doesn't affect anything. Can someone shed some light on what is going wrong here? If it's the-O1
flag, how do I override that?The text was updated successfully, but these errors were encountered: