Where Jump is the name of the instruction, and N is the offset which is
Jump_Insn's address + signed value provided by the N value = New_Address to
PPP = Extra bits that are used by compiler to pass values.
Now, let's say we have this following code:
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.
Balaji V. Iyer.
PS. Please CC me when responding since I am not a subscribed to this list.
Re: GAS overwrittes important bits when reading from symbol table
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
HTH you meanwhile until someone with really profound knowledge responds.
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.