[Gold] Question: Arm BE8 implementation
bharathi seshadri
bharathi.seshadri@gmail.com
Tue Jun 28 16:48:00 GMT 2016
Hello,
I'm trying to implement BE8 support in the gold linker for Arm.
The bfd linker uses elf32_arm_section_map to determine the range of
addresses for byte swapping before writing out the section. Is it
accurate to say that the equivalent data structure in gold is
mapping_symbols_info in class Arm_relobj ? Using small examples, I'm
able to see that all the required address ranges are covered in this
mapping table (except the plt).
I'm having some difficulty in deciding the right place to introduce
the swaps in gold, which should happen after all relaxation and
relocation are completed. From my limited understanding of the code,
in Arm_relobj::do_relocate_sections, all sections in an object file
have been relocated and should be a good place to insert the byte
swaps. I went ahead and implemented the byte swapping before returning
from Arm_relobj::do_relocate_sections using the information from
Arm_relobj::mapping_symbols_info. However, for a simple example, I see
that some ranges are not swapped in the final executable, even though
those ranges are being processed for swapping. This makes me suspect
that either I'm not swapping at the right place or in the right output
view.
I'm attaching my current patch in progress. Any pointers would be very helpful.
Thanks,
Bharathi
-------------- next part --------------
*** arm.cc.orig Thu Jun 23 15:48:12 2016
--- arm.cc Fri Jun 24 15:43:15 2016
*************** Arm_relobj<big_endian>::do_relocate_sect
*** 6610,6615 ****
--- 6610,6673 ----
section_address,
section_size);
}
+
+ // BE8 swapping
+ if (parameters->options().user_set_be8()) {
+
+ section_size_type span_start, span_end;
+
+ elfcpp::Shdr<32, big_endian> shdr(pshdrs + i * elfcpp::Elf_sizes<32>::shdr_size);
+ Mapping_symbol_position section_start(i, 0);
+ typename Mapping_symbols_info::const_iterator p =
+ this->mapping_symbols_info_.lower_bound(section_start);
+
+ while (p != this->mapping_symbols_info_.end() && p->first.first == i)
+ {
+ typename Mapping_symbols_info::const_iterator next =
+ this->mapping_symbols_info_.upper_bound(p->first);
+
+ // Only scan part of a section with arm code.
+ if (p->second == 'a') {
+ Output_section* os = this->output_section(i);
+ gold_assert(os != NULL);
+ Arm_address section_address = this->simple_input_section_output_address(i, os);
+ span_start = convert_to_section_size_type(p->first.second);
+ if (next != this->mapping_symbols_info_.end() && next->first.first == i)
+ span_end = convert_to_section_size_type(next->first.second);
+ else
+ span_end = convert_to_section_size_type(shdr.get_sh_size());
+ gold_info("MappingSymbolInfo %x %x", section_address+span_start, section_address +span_end);
+ unsigned char* view = (*pviews)[i].view;
+ Arm_address view_address = (*pviews)[i].address;
+ section_size_type view_size = (*pviews)[i].view_size;
+ unsigned char* section_view = view + (section_address - view_address);
+ uint64_t section_size = this->section_size(i);
+
+ gold_assert(section_address >= view_address
+ && ((section_address + section_size)
+ <= (view_address + view_size)));
+
+ unsigned int ptr = 0;
+ unsigned char tmp;
+ while (ptr + 3 < (span_end - span_start)) {
+ //gold_info("Value before swap %2x%2x%2x%2x", section_view[ptr+0], section_view[ptr+1],
+ // section_view[ptr+2], section_view[ptr+3]);
+ tmp = section_view[ptr];
+ section_view[ptr] = section_view[ptr + 3];
+ section_view[ptr + 3] = tmp;
+ tmp = section_view[ptr + 1];
+ section_view[ptr + 1] = section_view[ptr + 2];
+ section_view[ptr + 2] = tmp;
+ gold_info("Value after swap %2x%2x%2x%2x", section_view[ptr+0], section_view[ptr+1],
+ section_view[ptr+2], section_view[ptr+3]);
+ ptr += 4;
+ }
+ }
+ p = next;
+ }
+
+ }
+
}
}
*************** Output_data_plt_arm_standard<big_endian>
*** 7775,7780 ****
--- 7833,7853 ----
// Last word in first PLT entry is &GOT[0] - .
elfcpp::Swap<32, big_endian>::writeval(pov + 16,
got_address - (plt_address + 16));
+
+ if (parameters->options().user_set_be8()) {
+ unsigned char *oview = pov;
+ unsigned int ptr = 0;
+ unsigned char tmp;
+ while (ptr + 3 < 16) {
+ tmp = oview[ptr];
+ oview[ptr] = oview[ptr + 3];
+ oview[ptr + 3] = tmp;
+ tmp = oview[ptr + 1];
+ oview[ptr + 1] = oview[ptr + 2];
+ oview[ptr + 2] = tmp;
+ ptr+=4;
+ }
+ }
}
// Subsequent entries in the PLT.
*************** Output_data_plt_arm_standard<big_endian>
*** 7806,7811 ****
--- 7879,7899 ----
elfcpp::Swap<32, big_endian>::writeval(pov + 4, plt_insn1);
uint32_t plt_insn2 = plt_entry[2] | (offset & 0xfff);
elfcpp::Swap<32, big_endian>::writeval(pov + 8, plt_insn2);
+
+ if (parameters->options().user_set_be8()) {
+ unsigned char *oview = pov;
+ unsigned int ptr = 0;
+ unsigned char tmp;
+ while (ptr + 3 < 12) {
+ tmp = oview[ptr];
+ oview[ptr] = oview[ptr + 3];
+ oview[ptr + 3] = tmp;
+ tmp = oview[ptr + 1];
+ oview[ptr + 1] = oview[ptr + 2];
+ oview[ptr + 2] = tmp;
+ ptr+=4;
+ }
+ }
}
// Write out the PLT. This uses the hand-coded instructions above,
*************** Target_arm<big_endian>::do_adjust_elf_he
*** 10541,10547 ****
e_ident[elfcpp::EI_OSABI] = 0;
e_ident[elfcpp::EI_ABIVERSION] = 0;
! // FIXME: Do EF_ARM_BE8 adjustment.
// If we're working in EABI_VER5, set the hard/soft float ABI flags
// as appropriate.
--- 10629,10639 ----
e_ident[elfcpp::EI_OSABI] = 0;
e_ident[elfcpp::EI_ABIVERSION] = 0;
! // Do EF_ARM_BE8 adjustment.
! if (parameters->options().user_set_be8()) {
! flags |= elfcpp::EF_ARM_BE8;
! this->set_processor_specific_flags(flags);
! }
// If we're working in EABI_VER5, set the hard/soft float ABI flags
// as appropriate.
More information about the Binutils
mailing list