GAS overwrittes important bits when reading from symbol table

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

GAS overwrittes important bits when reading from symbol table

Balaji V. Iyer
Hi Everyone,
      I am currently using binutils 2.11.93 for a proprietary processor.

Here is the line for the jump instruction:

{"jump",       "N",            "00 0x0 NNNNN NNNNN NNNN NNNN NNNN NPPP",

Where Jump is the name of the instruction, and N is the offset which is
computed by

Jump_Insn's address + signed value provided by the N value = New_Address to
Jump to.

PPP = Extra bits that are used by compiler to pass values.

Now, let's say we have this following code:

_start:   --
          --
          jump _main
          --
          --
          --
          --

_main:    --
            --


The Assembler looks for the "_main" value in the symbol table (which
obviously doesn't exist when it is reading the jump instruction and then it
does a zero filling. Then right before writing the bits into the file, it
cross references with the symbol table and looks for the offset of "_main"
and puts them in the jump instruction (I think, NOT 100% sure!!).

The problem is that, it overwrites the "PPP" bits. How can I make it not do
this? Where exactly does this writing of the offset of main takes place?


Any help is highly appreciated.

Thanking You,

Yours Sincerely,

Balaji V. Iyer.

PS. Please CC me when responding since I am not a subscribed to this list.

Reply | Threaded
Open this post in threaded view
|

Re: GAS overwrittes important bits when reading from symbol table

Bjoern Haase
Hi,

I'd suggest that you look wether the value of the symbol is inserted by the
linker or by the assembler. I'd rather assume it's the linker.

Use objdump -d -r unlinked-object-file-name in order to find out if the
reference to the main function is still present in the object file after
assembling the function.

If it's indeed the assembler, you should look for the assembler functions that
are responsible for the "fixups". If the problem is within gas the
responsible code should end up (IIUC with my limited knowledge) in the
gas/config directory of binutils.

If the problem occures during linking you will have to look at the bfd
directory instead. It might help to search a function carrying the keyword
"final_link_relocate".

Bjoern

P.S.:
HTH you meanwhile until someone with really profound knowledge responds.
Reply | Threaded
Open this post in threaded view
|

Re: GAS overwrittes important bits when reading from symbol table

DJ Delorie-2
In reply to this post by Balaji V. Iyer

Well, it depends on how your proprietary assembler was written.  Since
you don't say, we can't help you much, but here is some general help.

When parsing opcodes, gas builds a list of "fragments" that are
partially filled in on the first pass (and may be varying in size if
the size of the opcode is not known on the first pass).  Additionally,
a set of fixups are created that connect the operand fields of each
opcode to the addresses they refer to.  Each fixup has a fixup type,
which tells gas and ld *how* to put the value into that field.

If the symbol is defined locally, gas can usually put the value in.
Look for a function called md_convert_frag in gas/config/tc-*.c

If the symbol isn't local, gas emits a relocation which is filled in
by the linker.  Look for a function like *_relocate_section or
*_final_link_relocate in your target-specific bfd/*.c

The relocation for your jump would have to be specific to a field that
has three bits that must be preserved; you can't use a generic 26 bit
relocation.  Perhaps something like R_MYCPU_JUMP_26_3.  Both gas and
bfd would use this relocation to mean "leave the lower three bits
alone" so the code would have to know to mask those bits properly.