This is a cut-down version of the problem I'm facing on AArch64:
I've this macro that keeps dumping some data into a section.
#define GEN_DATA(_type) \ .pushsection .mydata_##_type, "aw"; \ .ifndef start; \ start:; \ .endif; \ .word 1; \ .reloc end_loc, R_AARCH64_ABS64, .; \ .popsection
I eventually wanted to capture the start and end of similar types in a structure like this:
.pushsection .head, "aw" .quad start end_loc: .quad 0 .popsection
I can track where the section starts with the start
symbol. I don't know in advance how many invocations of GEN_DATA()
will be there in the build, so I can't define an end
. I don't know how many _type
s of section will be used either, so can't place guard symbol script. Therefore I decided to leave a relocation entry for end_loc
so that linker will eventually fixup where the whole section ends. Yes, there will be multiple relocation entries for the same end_loc
, but because they're absolute relocations, I reckon they don't conflict.
I had hunch, but in the final binary, end_loc
is getting fixed up with a wrong address. I'll blame it on multiple relocation entries, but the weird thing is that, everything is OK if I also add a dummy, extra relocation entry too -- I.e. I modify the structures above to:
#define GEN_DATA(_type) \ .pushsection .mydata_##_type, "aw"; \ .ifndef start; \ start:; \ .endif; \ .word 1; \ .reloc end_loc, R_AARCH64_ABS64, .; \ .reloc dummy_loc, R_AARCH64_ABS64, .; \ .popsection
and:
.pushsection .head, "aw" .quad start end_loc: .quad 0 dummy_loc: .quad 0 .popsection
So I'm wondering:
Why is
end_loc
getting fixed up wrongly? What's wrong with multiple absolute relocation entries, if at all? Isn't the linker expected to go through them in order, and the last one falls into effect?Why would simply adding a dummy relocation make everything right?
Basically, what's going on?!
And finally, are there any alternatives approaches that I could try?
EDIT: I've now pushed the sample code to a Git repository. Use make
and make broken=1
to view the disassembly. Needs Linaro AArch64 tool chain in $PATH
.
I don't know what's going on with the relocations, but the easiest way to do what you're trying accomplish is to use a linker script. This will let you group all the
.mydata_XXX_type
sections together and provide symbols for the start and end of the grouped sections. Something like this:Which you would use with an assembly file like this:
(I've used assembler macros instead of C macros because they're much easier to work with.) You'd use the two above files like this:
If you know all the possible section "types" then you do it without using a linker script by relying on the fact the linker places unknown sections in the order it first encounters them. For example:
If you have multiple assembler files using the macro make sure that all the assembler files include the
.section
directives shown above at the start so it doesn't matter which order they appear on the linker command line.Note that both solutions resolve a problem with your macro, it's possible other unknown sections can be placed in between your
.mydata_XXX_type
sections if they happen to appear to the linker for the first time in that order.