Hi,
In this file: kernel-debuginfo-2.6.29-0.258.rc8.git2.fc11.i586:usr:lib:debug:lib:modules:2.6.29-0.258.rc8.git2.fc11.i586:vmlinux
I'm seeing relocations that seem wrong: the addend and the value of the symbol the relocation is done against are the same.
Relocation section [71] '.rel.debug_aranges' for section [70] '.debug_aranges' at offset 0x4d1d0dc contains 4309 entries: Offset Type Value Name 0x00000006 386_32 0000000000 .debug_info 0x00000010 386_32 0xc0400000 .text.head
Section Headers: [Nr] Name Type Addr Off Size ES Flags Lk Inf Al [ 0] NULL 00000000 000000 000000 0 0 0 0 [ 1] .text.head PROGBITS c0400000 001000 0003b1 0 AX 0 0 16 [ 2] .rel.text.head REL 00000000 4b3313c 0001e0 8 87 1 4 [ 3] .text PROGBITS c0400400 001400 2f33ca 0 AX 0 0 128
Symbol table [87] '.symtab' contains 40473 entries: 29807 local symbols String table: [88] '.strtab' Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UNDEF 1: c0400000 0 SECTION LOCAL DEFAULT 1 2: c0400400 0 SECTION LOCAL DEFAULT 3 3: c06f37cc 0 SECTION LOCAL DEFAULT 5
And objdump just to be sure: Contents of section .debug_aranges: 0000 1c000000 02000000 00000400 00000000 ................ 0010 000040c0 b1030000 00000000 00000000 ..@............. 0020 1c000000 02007d00 00000400 00000000 ......}.........
Unless I'm wrong here, what I see is relocation with addend 0xc0400000, formed against .text.head, whose address also is 0xc0400000, resulting in relocated address 0x180800000, or 0x80800000 after 32-bit wrapping (which I made up right now, dwarflint forgets to do this). That doesn't fall into any section. Bug, or am I missing something?
PM
In this file: kernel-debuginfo-2.6.29-0.258.rc8.git2.fc11.i586:usr:lib:debug:lib:modules:2.6.29-0.258.rc8.git2.fc11.i586:vmlinux
This is not an ET_REL file. It's a final link that uses --emit-relocs. The DWARF data (and all the rest) is fully relocated already.
The kernel build uses --emit-relocs for the benefit of some post-processing that turns the relocs (for allocated sections) into one big table used at runtime to do simple in-place adjustments. (Though the kernel binary is ET_EXEC, basically it acts as if it were an ET_DYN with DT_TEXTREL and all its relocs being just R_386_RELATIVE.)
To start with, it is probably fine not to even look for relocs in files that are not ET_REL. Whatever relocs they have are "extra information" and not really needed to make sense of the DWARF data. (But I'll continue with the details of interpreting this data, in case we want to do the extra checking just because.)
I'm seeing relocations that seem wrong: the addend and the value of the symbol the relocation is done against are the same.
These are SHT_REL, not SHT_RELA. It doesn't have an addend, it only has an in-place value. When relocation still has to be done (as in an ET_REL), the value in place acts as the addend (i.e. symbol value applied with +=). When relocation has already been done, obviously this cannot be so. The final value is in place, and any original nonzero "addend" is lost.
This is why prelink converts SHT_REL to SHT_RELA, btw. In prelink cases, the symbol is usually an undefined external. Hence it has no way to figure out the "original" symbol value added to the original "addend" in place.
Here we always have the original symbol value. We can "derelocate" the in-place value by subtracting the symbol value to recover the lost addend.
In normal non-ET_REL files, the relocs left in allocated sections are those in the dynamic relocs. That is, SHT_REL{,A} sections that are SHF_ALLOC themselves. Those are "normal" relocs, i.e. that have not been applied yet so in-place values are just the addends (in SHT_REL).
I suppose if someone used --emit-relocs in a normal dynamic link of an executable or DSO, there might be both a dynamic reloc (in an SHT_REL,SHF_ALLOC section) and a preserved reloc (in an SHT_REL,~SHF_ALLOC reloc section) pointing to the same location in an allocated section. But nobody does that. Moreover, in dwarflint we are only checking the relocs that apply to non-allocated sections. For all those, it is unambiguous that the relocs have already been applied to the non-allocated section data.
Eventually we might want to be checking .eh_frame, the only allocated section containing a DWARFish format. In the outlying cases of pure theory, .eh_frame could have dynamic relocs and have this ambiguity if it also has --emit-relocs relocs. But, 1. the compiler is always smart enough to emit .eh_frame for PIC without TEXTREL 2. nobody really uses --emit-relocs with this 3. we will not be touching .eh_frame with the DWARF writer, it's an allocated section--so dwarflint checks on it are not crucial for our correctness checking (just for verifying against gcc/as/ld bugs) 4. we might decide to touch/rewrite .eh_frame in the DWARF writer, but would do so only in ET_REL files where this is all moot
One day #2 will probably stop being true in the kernel, because it will start to have .eh_frame itself. But it is statically linked with --emit-relocs and never produces dynamic relocs, so again there is no ambiguity.
So, the "more than complete enough" checking plan (i.e. where you bother with reloc checks in non-ET_REL at all) would be as follows. For a reloc in an SHT_REL (not SHT_RELA) section in a non-ET_REL file, subtract the symbol value (and barf if it's SHN_UNDEF)--note that since it's an ET_REL, the st_value is the final value directly, not section-relative. If there is an SHT_REL,SHF_ALLOC section that applies to the section you are checking, complain and punt (however you would if all its relocs were unknown types or whatnot). (If the SHT_REL,SHF_ALLOC section has a target section that is not SHF_ALLOC, elflint should complain about that.)
Thanks, Roland
On Fri, 17 Apr 2009 21:42:22 +0200, Roland McGrath wrote:
So, the "more than complete enough" checking plan (i.e. where you bother with reloc checks in non-ET_REL at all) would be as follows. For a reloc in an SHT_REL (not SHT_RELA) section in a non-ET_REL file, subtract the symbol value (and barf if it's SHN_UNDEF)--note that since it's an ET_REL, the st_value is the final value directly, not section-relative. If there is an SHT_REL,SHF_ALLOC section that applies to the section you are checking, complain and punt (however you would if all its relocs were unknown types or whatnot). (If the SHT_REL,SHF_ALLOC section has a target section that is not SHF_ALLOC, elflint should complain about that.)
FYI there was a GDB discussion about ET_EXEC relocations (in vmlinux), Alan Modra's advice from it: http://sources.redhat.com/ml/gdb/2006-08/msg00144.html
But IIUC the checking vs. relocating operations are orthogonal here.
Regards, Jan
FYI there was a GDB discussion about ET_EXEC relocations (in vmlinux), Alan Modra's advice from it: http://sources.redhat.com/ml/gdb/2006-08/msg00144.html
Indeed, for making use of it for debugging they are just irrelevant.
But IIUC the checking vs. relocating operations are orthogonal here.
Right. This is really an academic discussion about the extremes of what dwarflint could do to be a thorough checker of toolchain bugs including in the --emit-relocs behavior of ld.
Thanks, Roland
Roland McGrath wrote:
In this file: kernel-debuginfo-2.6.29-0.258.rc8.git2.fc11.i586:usr:lib:debug:lib:modules:2.6.29-0.258.rc8.git2.fc11.i586:vmlinux
This is not an ET_REL file. It's a final link that uses --emit-relocs. The DWARF data (and all the rest) is fully relocated already.
The kernel build uses --emit-relocs for the benefit of some post-processing that turns the relocs (for allocated sections) into one big table used at runtime to do simple in-place adjustments. (Though the kernel binary is ET_EXEC, basically it acts as if it were an ET_DYN with DT_TEXTREL and all its relocs being just R_386_RELATIVE.)
To start with, it is probably fine not to even look for relocs in files that are not ET_REL. Whatever relocs they have are "extra information" and not really needed to make sense of the DWARF data. (But I'll continue with the details of interpreting this data, in case we want to do the extra checking just because.)
I'm seeing relocations that seem wrong: the addend and the value of the symbol the relocation is done against are the same.
These are SHT_REL, not SHT_RELA. It doesn't have an addend, it only has an in-place value. When relocation still has to be done (as in an ET_REL), the value in place acts as the addend (i.e. symbol value applied with +=). When relocation has already been done, obviously this cannot be so. The final value is in place, and any original nonzero "addend" is lost.
This is why prelink converts SHT_REL to SHT_RELA, btw. In prelink cases, the symbol is usually an undefined external. Hence it has no way to figure out the "original" symbol value added to the original "addend" in place.
Here we always have the original symbol value. We can "derelocate" the in-place value by subtracting the symbol value to recover the lost addend.
Is this useful for anything?
In normal non-ET_REL files, the relocs left in allocated sections are those in the dynamic relocs. That is, SHT_REL{,A} sections that are SHF_ALLOC themselves. Those are "normal" relocs, i.e. that have not been applied yet so in-place values are just the addends (in SHT_REL).
I suppose if someone used --emit-relocs in a normal dynamic link of an executable or DSO, there might be both a dynamic reloc (in an SHT_REL,SHF_ALLOC section) and a preserved reloc (in an SHT_REL,~SHF_ALLOC reloc section) pointing to the same location in an allocated section. But nobody does that. Moreover, in dwarflint we are only checking the relocs that apply to non-allocated sections. For all those, it is unambiguous that the relocs have already been applied to the non-allocated section data.
Eventually we might want to be checking .eh_frame, the only allocated section containing a DWARFish format. In the outlying cases of pure theory, .eh_frame could have dynamic relocs and have this ambiguity if it also has --emit-relocs relocs. But,
- the compiler is always smart enough to emit .eh_frame for PIC without TEXTREL
- nobody really uses --emit-relocs with this
- we will not be touching .eh_frame with the DWARF writer, it's an allocated section--so dwarflint checks on it are not crucial for our correctness checking (just for verifying against gcc/as/ld bugs)
- we might decide to touch/rewrite .eh_frame in the DWARF writer, but would do so only in ET_REL files where this is all moot
One day #2 will probably stop being true in the kernel, because it will start to have .eh_frame itself. But it is statically linked with --emit-relocs and never produces dynamic relocs, so again there is no ambiguity.
So, the "more than complete enough" checking plan (i.e. where you bother with reloc checks in non-ET_REL at all) would be as follows. For a reloc in an SHT_REL (not SHT_RELA) section in a non-ET_REL file, subtract the symbol value (and barf if it's SHN_UNDEF)--note that since it's an ET_REL,
(non-ET_REL I assume)
the st_value is the final value directly, not section-relative. If there is an SHT_REL,SHF_ALLOC section that applies to the section you are checking, complain and punt (however you would if all its relocs were unknown types or whatnot). (If the SHT_REL,SHF_ALLOC section has a target section that is not SHF_ALLOC, elflint should complain about that.)
At this time, dwarflint gives an error if ET_REL file misses a relocation, but does relocation even in non-ET_REL files, if they are present. According to what you say, it should instead ignore relocation sections in non-ET_REL files.
Now what about DW_OP_call_ref, and others that Dwarf3 document claims to be "relocatable in a relocatable object file, and relocated in an executable or shared object"? These are basically the reason why I never had any doubts that I should handle relocations in non-ET_REL files.
Alan Modra's advice (from Jan's email, ignoring relocs that use normal symbol table) seems reasonable to me.
PM
Here we always have the original symbol value. We can "derelocate" the in-place value by subtracting the symbol value to recover the lost addend.
Is this useful for anything?
Only to recover the symbol+addend so as to check the reloc in common with the ET_REL treatment.
symbol value (and barf if it's SHN_UNDEF)--note that since it's an ET_REL,
(non-ET_REL I assume)
the st_value is the final value directly, not section-relative. If there
Yes, sorry about the typo/braino.
At this time, dwarflint gives an error if ET_REL file misses a relocation, but does relocation even in non-ET_REL files, if they are present. According to what you say, it should instead ignore relocation sections in non-ET_REL files.
That would be fine, yes.
Now what about DW_OP_call_ref, and others that Dwarf3 document claims to be "relocatable in a relocatable object file, and relocated in an executable or shared object"? These are basically the reason why I never had any doubts that I should handle relocations in non-ET_REL files.
These are just like DW_FORM_ref_addr and all the offset_size header fields. For them "relocated" means resolved as relative to the target section, i.e. as if it had been an allocated section with sh_addr=0. In all normal non-ET_REL files, you will not have any relocs for these either. Only with --emit-relocs (or tool bugs) will there be reloc sections for any of the nonallocated sections at all.
Alan Modra's advice (from Jan's email, ignoring relocs that use normal symbol table) seems reasonable to me.
Except for anomalies (that elflint should catch if it doesn't already), this will be the same as ignoring SHT_REL/SHT_RELA sections that are not themselves SHF_ALLOC.
Thanks, Roland
elfutils-devel@lists.fedorahosted.org