LTO archive test#1050
Conversation
| @@ -0,0 +1,5 @@ | |||
| //#LinkArgs:-L./ -lexample | |||
|
|
|||
| extern int CRC32_ProcessSingleBuffer(void const*, int); | |||
There was a problem hiding this comment.
Declaring an extern function won't actually cause a reference to the symbol to be emitted. The code needs to actually refer to the symbol - e.g. from main.
There was a problem hiding this comment.
It's fine to add this file to experimentation, but I think if we wanted to merge this PR, we'd need to figure out how to build a similar file from source.
218c518 to
960e365
Compare
|
Apologies for pushing prematurely. There is an issue I need to fix. But, the changes mentioned above have been added. |
960e365 to
0a01569
Compare
|
|
||
| extern int addition(int, int); | ||
|
|
||
| int main(int argc, char **argv) { |
There was a problem hiding this comment.
Most of our tests use _start rather than main. _start is the default entry point for the binary. main is called sometime later by the libc runtime. A few of our tests do use main, but we only do that when necessary, since it requires linking against libc, which substantially slows down linking. I suspect the reason you're seeing a failure is because you haven't defined _start and also haven't linked against libc. I'd suggest looking at a test like trivial.c to see how the _start-based tests are written.
There was a problem hiding this comment.
That makes sense. I incorrectly assumed libc was linked automatically for testing since I used main in my z-defs testing. I saw the Requires set of flags but didn't put two and two together. Pushing fixes now, the error is now, correctly, the undefined symbol error showing archives avoid the LTO guard. I still have the issue we discussed earlier of accessing the archive's sections at the point we emit the undefined error to emit an LTO error rather than an undefined error.
0a01569 to
edc398c
Compare
|
Looking at one of the test failures: This is failing to link with ld. i.e. it hasn't actually gotten to linking with wild, which happens after GNU ld. GNU ld looks to be failing because the linker plugin wasn't passed as an argument. I guess that suggests that for this test, we do need to use the C compiler to drive the linker rather than invoking the linker directly. If you look at |
edc398c to
30dd1cc
Compare
|
The test should be good now! |
|
Cool, yep that failure does indeed show that we're still giving an undefined symbol error rather than a more appropriate error. I suspect #979 might have actually regressed that, but I don't think we want to undo that change, since that would hurt performance. The issue is that we now only look for LTO sections in archive entries that we activate, but we never activate the relevant archive entry because it doesn't define any any needed symbols in its symtab. One possibility would be that if we detect that we've got an undefined symbol error, we go back and scan all archived objects that we didn't already process. If any turn out to have LTO bitcode, then make that be the error instead of the undefined symbol error. |
|
There was something about the tests that was confusing me. If you run |
fixed: test to build own archive and use function removed: unecessary linker args fixed: lto archive test no longer requires libc link fixed: ld needs lto plugin from gcc to work fixed: lto test to avoid ld error
improved: error message and test fixed: cargo fmt
00829c2 to
785793a
Compare
|
I'm not quite sure why the tests aren't passing. They pass locally and are giving the error message I expect and catch in the test header. Edit: I realize what the problem is. I'll push a fix. |
fixed: formating
1135d6e to
629bb4a
Compare
| .expect("Canonicalized path can't have ../ at end") | ||
| .to_str() | ||
| .expect("File name should be valid UTF-8") | ||
| .split(".") |
There was a problem hiding this comment.
Why are you only taking the filename up to '.'?
There was a problem hiding this comment.
The file generated is archive_lto.a. I believe that the linker adds something to the end of the object file extracted into memory when parsing the archive. I thought it would better to give the name of the actual archive file and avoid the random values. This is the error I mentioned fixing above where the test would pass locally but not in github actions. I never checked where these values are being added onto the name. If we are able to know what it is and add the appropriate value to the Expected header value, it is possible that this is entirely unnecessary.
There was a problem hiding this comment.
I suspect the extra stuff in the filename is added by the integration testing framework, so it's actually part of the filename.
There was a problem hiding this comment.
After reading integration_tests.rs and reviewing the commits, I see you're 100% right. The command is hashed as part of the file name, and I added the //#SkipLinker:ld directive between commits. I'll change that and everything should be good.
| .symbol_name(symbol_id) | ||
| .expect("Errored on symbol {symbol_name} so it exists"); | ||
| let mut lto_file: Option<&PathBuf> = None; | ||
| let lto_unresolved = resources.symbol_db.groups.iter().any(|group| match group { |
There was a problem hiding this comment.
Is lto_unresolved actually needed? It looks like it's always true when lto_file is Some and false when lto_file is None. Perhaps just replace the two any calls with find_map.
There was a problem hiding this comment.
That's fair. I was originally just checking if the undefined symbol came from a file with lto, but I then realized I needed to add the file name in the error message.
| if args.error_unresolved_symbols { | ||
| let raw_symbol_name = symbol_db | ||
| .symbol_name(symbol_id) | ||
| .expect("Errored on symbol {symbol_name} so it exists"); |
There was a problem hiding this comment.
Note that the {symbol_name} won't substitute the variable symbol_name.
There was a problem hiding this comment.
I didn't know that expect doesn't format strings. Thanks for pointing it out!
| let raw_symbol_name = symbol_db | ||
| .symbol_name(symbol_id) | ||
| .expect("Errored on symbol {symbol_name} so it exists"); | ||
| let mut lto_file: Option<&PathBuf> = None; |
There was a problem hiding this comment.
This method is already pretty large and adding this makes it ever larger. Could something be moved out to a separate function? Perhaps the code to compute lto_file?
There was a problem hiding this comment.
That makes sense. Will work on it.
6e306fa to
51d84e5
Compare
PRs #91, #744, and #979 should be sufficient to resolve issue #464. But, I think this test highlights the need for more work on the issue. However, I'm not entirely sure if the test is erroneously written. It gets past the LTO guard, but it doesn't error on an undefined symbol as one would expect. Instead, it errors on "Binary ran for too long."