extracting relocation info from COFF from "section contents" base d on partial_inplace

Dave Korn dk@artimi.com
Thu Apr 8 17:20:00 GMT 2004


> -----Original Message-----
> From: binutils-owner On Behalf Of Liang, James
> Sent: 08 April 2004 17:12

> I'm writing a port of objcopy that takes COFF as input.  The 
> problem is that
> I can't seem to get all of the relocation
> information I need.  Specifically, I'm missing some info from 
> some imported
> symbols.  The Howto section does not give me
> enough information to relocate, but does give me 'true" flags 
> for pcrel and
> partial_inplace.
> 
> From the info section of BFD, I get that these flags mean 
> they're stored in
> the "section contents", but I have no idea how to extract them.
> How do I get these values?

  The 'section contents' mean those bytes that make up the actual data in
the section - .text, .data or whichever - that the reloc is issued against.

  There are two ways relocs can be (are) implemented.  In ELF terms, you'd
be looking here at the distinction between USE_RELA and USE_REL relocations;
I'm going to extend these terms to non-elf systems as well.  From here on,
regard "USE_REL" as a synonym for "partial_inplace is true".

  One is for the reloc to contain all the information needed to perform the
relocation calculation: so it has to specify a destination (the address in
the section of the instruction or pointer that's actually being relocated),
a symbol (which the relocation refers to) and an optional offset (relative
to the relocation symbol).

  Under some target/architectures, all these data are stored in the reloc.
When final link time comes, ld looks at the data in the reloc, finds the
symbol it's against, looks up the value of that symbol, applies any offset
relative to the symbol, applies a further offset against the destination of
the reloc (only in the case of pc-relative relocs), and then has to go and
put the result into the pointer or opcode or whatever is at the destination.

  Normally the destination will be either some kind of memory location where
a pointer to another address is stored, or a machine code instruction that
directly addresses memory and has a memory address operand encoded into the
instruction itself somehow; and normally, when the linker has performed the
relocation calculation described above, it then has to encode the result
into the destination - that's a simple store operation in the case of a
pointer, or a shift-and-mask operation when it's performing surgery on the
address field of an instruction opcode.

  Under the USE_REL scheme, however, an efficiency saving is made.  Because
the space has to be there in the section contents for the pointer or opcode
or whatever that is the target of the relocation, we make use of that target
to store the relocation offset.  So the offset is placed into either the
pointer or the address field of the instruction opcode, and saves space in
the reloc tables.  That's why it's also called 'partial_inplace': because
part of the reloc information (the offset) is already in-place: in the place
where it has to end up after the final calculation.

  Here's an example:  Consider the C code

-------------------
static char a[];
char i;

	i = a[512];
-------------------

which might compile to something like this (taking m68k as an example just
to make the syntax real:)

     mov.b  d0,_a+512

  Now the assembler has to translate this instruction into an actual machine
code opcode and a relocation information entry.  Here's how it would look
under the two schemes:

 - RELA: assembler issues the instruction with zero in the address field but
a full RELA structure in the relocation info:

     mov.b  d0,$0000
RELA: dst = (addr of mov.b), symbol = _a, offset = 512

  - REL: But under the USE_REL scheme, the assembler would issue:

     mov.b  d0,$0200
REL: dst = (addr of mov.b), symbol = _a

  Get it?  The instruction contains a field that is big enough to contain
the offset (it has to be, since the final result of symbol+offset is going
to be stored into there), so why not use that field to store the offset in
the relocatable .o files and save space in the relocation structures?

  In practical terms, this means that if in your object file format you find
(rel->addend == 0) all the time, that means you have to look at using of of
the bfd functions such as bfd_get_int32 (or other size, depending on the
type of relcoc; and I may have slightly misremembered the name anyway) that
fetches bytes out of your input section and use them to find what the addend
should be.

    cheers, 
      DaveK
-- 
Can't think of a witty .sigline today....



More information about the Binutils mailing list