[PATCH 3/6] bfd: refine handling of relocations between debugging sections

Jan Beulich jbeulich@suse.com
Thu Mar 4 09:00:58 GMT 2021


On 04.03.2021 07:10, Alan Modra wrote:
> On Tue, Mar 02, 2021 at 10:48:30AM +0100, Jan Beulich via Binutils wrote:
>> Preliminary remark: While relevant for Dwarf in particular, I would
>> assume other debug info formats have similar implications. If not, I've
>> no idea how to correctly deal with the Dwarf case.
>>
>> Dwarf wants references between the various .debug_* sections to be
>> section relative. ELF, however, has section relative relocations on only
>> very few architectures. Hence normal 32-bit / 64-bit data relocations
>> get used (the ones with correspond to BFD_RELOC_{32,64}). For ELF output
>> this is not a problem by default as all these sections get placed at VA
>> zero. For PE output using VA 0 is not an option, as that would place the
>> section below the image base (see also "bfd: don't silently wrap or
>> truncate PE image section RVAs"). And even for ELF output this can be a
>> problem if these sections get assigned real VAs, e.g. when a program or
>> library wants to be able to access its own debug info.
> 
> So this is for linking ELF with debug info into PE output?

It's unavoidable for this case, yes, but as said even for ELF it can
turn out to be necessary (when the .debug_* sections get assigned a
non-zero [and large enough] VA).

>> --- a/bfd/reloc.c
>> +++ b/bfd/reloc.c
>> @@ -749,6 +749,30 @@ bfd_perform_relocation (bfd *abfd,
>>    else
>>      output_base = reloc_target_output_section->vma;
>>  
>> +  /* Most architectures have no section relative ELF relocations.  They use
>> +     ordinary ones instead for representing section relative references between
>> +     debugging sections, which works fine as long as the section VMA gets set
>> +     to zero.  While this is the default for ELF output (albeit not a
>> +     requirement), in particular PE doesn't even allow zero VMAs for any of the
>> +     sections.  */
>> +  if(output_base && !howto->pc_relative
>> +     && bfd_get_flavour (abfd) == bfd_target_elf_flavour
>> +     && (reloc_target_output_section->flags
>> +	 & input_section->flags & SEC_DEBUGGING))
>> +    {
>> +      /* Since this is a heuristic, apply further checks in an attempt to
>> +	 exclude relocation types other than simple base ones.  */
>> +      unsigned int size = bfd_get_reloc_size (howto);
>> +
>> +      if (size && !(size & (size - 1))
>> +          && !(howto->bitsize & (howto->bitsize - 1))
>> +          && !howto->bitpos && !howto->rightshift
>> +          && !howto->negate && !howto->partial_inplace
>> +          && !(howto->src_mask & (howto->src_mask + 1))
>> +          && !(howto->dst_mask & (howto->dst_mask + 1)))
>> +	output_base = 0;
>> +    }
>> +
>>    output_base += symbol->section->output_offset;
>>  
>>    /* If symbol addresses are in octets, convert to bytes.  */
> 
> When we need this sort of horrible hack, it's time to redesign.

Well, I was fearing that, but I have to admit I have no idea what
would need doing where. Surely the "horrible" aspects could be
reduced by limiting the number of extra checks - as said in
comment and description, I've added them to reduce risk of
mistakenly zapping output_base. But I definitely agree that no
matter how much massaging would be done, it's probably going to
remain ugly without finding an entirely different approach.

This said, I had to admit that I was actually inspired by this
code a few lines up from where I did the addition:

  /* Convert input-section-relative symbol value to absolute.  */
  if ((output_bfd && ! howto->partial_inplace)
      || reloc_target_output_section == NULL)
    output_base = 0;

I may not fully understand the reasons behind it, but it as well
did look like a hack to me.

Jan


More information about the Binutils mailing list