bug-binutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug binutils/30719] New: Relocation offset of IMAGE_REL_AMD64_ADDR32NB


From: mateusz.karcz at interia dot eu
Subject: [Bug binutils/30719] New: Relocation offset of IMAGE_REL_AMD64_ADDR32NB discarded when linking into elf64-x86-64
Date: Fri, 04 Aug 2023 11:48:43 +0000

https://sourceware.org/bugzilla/show_bug.cgi?id=30719

            Bug ID: 30719
           Summary: Relocation offset of IMAGE_REL_AMD64_ADDR32NB
                    discarded when linking into elf64-x86-64
           Product: binutils
           Version: 2.38
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: binutils
          Assignee: unassigned at sourceware dot org
          Reporter: mateusz.karcz at interia dot eu
  Target Milestone: ---

Created attachment 15038
  --> https://sourceware.org/bugzilla/attachment.cgi?id=15038&action=edit
Build script generating five variants of the executable

Overview:
  While trying to embed Windows Resources inside Linux executable
  (I've been doing that with tkchia's IA-16 GCC before) I've noticed
  that when targetting x86-64, relocations within the .rsrc section
  are replaced with its base address instead of base+offset. I am
  trying to understand if it's a bug in binutils, or just it so
  happen that for i386 it works 'by accident' and my use scenario is
  invalid.

Steps to Reproduce:
  1) Prepare a simple RC file:
     ---------- resource.rc ----------
     // entry 6/1/1031
     STRINGTABLE
     LANGUAGE 1031, 1
     {
         0, "Hallo"
     }

     // entry 6/1/1033
     STRINGTABLE
     LANGUAGE 1033, 1
     {
         0, "Hello"
     }
     ----------

  2) Call windres (both i686-w64-mingw32 and x86_64-w64-mingw32 will
     result in the same content of .rsrc section) with .obj (COFF) as
     output format. The .rsrc section will have the following layout:

     0x00 IMAGE_RESOURCE_DIRECTORY for root
     0x10 IMAGE_RESOURCE_DIRECTORY_ENTRY (id 6, off 0x18)
     0x18 IMAGE_RESOURCE_DIRECTORY for 6
     0x28 IMAGE_RESOURCE_DIRECTORY_ENTRY (id 1, off 0x30)
     0x30 IMAGE_RESOURCE_DIRECTORY for 6/1
     0x40 IMAGE_RESOURCE_DIRECTORY_ENTRY (id 1031, off 0x50)
     0x48 IMAGE_RESOURCE_DIRECTORY_ENTRY (id 1033, off 0x60)
     0x50 IMAGE_RESOURCE_DATA_ENTRY for 6/1/1031 (at .rsrc+0x70)
     0x60 IMAGE_RESOURCE_DATA_ENTRY for 6/1/1033 (at .rsrc+0xA0)
     0x70 "Hallo"
     0xA0 "Hello"

  3) Link it with code into a full executable, in one of two ways:
     a. Use COFF as direct input of the linker (needs .rsrc section
        attribute in C source, reflected by NOOBJCOPY macro
        definition in my example).
     b. Use objcopy to convert COFF into ELF, while renaming .rsrc to
        .rodata.rsrc and adding a new symbol at its start.
     In both cases, I'm using -no-pie switch.

  I've prepared a build script (ATTACHMENT) which generates
  executables in five following variants:
  1) 32-bit .obj -> 32-bit .o -> 32-bit executable
  2) 64-bit .obj -> 32-bit .o -> 32-bit executable
  3) 64-bit .obj -> 64-bit .o -> 64-bit executable
  4) 32-bit .obj -> 32-bit executable
  5) 64-bit .obj -> 64-bit executable

Actual Result:
  In all 32-bit variants (1, 3, and 4) IMAGE_RESOURCE_DATA_ENTRY
  .OffsetToData fields point to "Hallo" (.rsrc+0x70) and "Hello"
  (.rsrc+0xA0) when loaded to memory, eg.:

    rsrc: 0x804a040
    6/1/1031 offset: 0x804a0b0
    6/1/1033 offset: 0x804a0e0

  In variant 3 all IMAGE_RESOURCE_DATA_ENTRY.OffsetToData fields
  point to the start of the .rsrc section (offset is discarded):

    rsrc: 0x40203c
    6/1/1031 offset: 0x40203c
    6/1/1033 offset: 0x40203c

  In variant 5 IMAGE_RESOURCE_DATA_ENTRY.OffsetToData fields seem to
  lack the image base address in memory (but offset is preserved):

    rsrc: 0x404030
    6/1/1031 offset: 0x40a0
    6/1/1033 offset: 0x40d0

  For examples, I was using the following C program:
  ---------- main.c ----------
  #include <stdint.h>
  #include <stdio.h>

  #ifndef NOOBJCOPY
  extern
  #endif
      char rsrc[]
  #ifdef NOOBJCOPY
      __attribute__((section(".rsrc"))) = {}
  #endif
  ;

  #pragma pack(push, 1)
  typedef struct
  {
      uint32_t OffsetToData;
      uint32_t DoNotCare[3];
  } IMAGE_RESOURCE_DATA_ENTRY;
  #pragma pack(pop)

  int main(void)
  {
      printf("rsrc: %p\n", rsrc);
      IMAGE_RESOURCE_DATA_ENTRY *entries =
          (IMAGE_RESOURCE_DATA_ENTRY *)(rsrc + 0x50);

      printf("6/1/1031 offset: %#lx\n",
          (long)entries[0].OffsetToData);
      printf("6/1/1033 offset: %#lx\n",
          (long)entries[1].OffsetToData);
      return 0;
  }
  ----------

Expected Result:
  I would expect 64-bit variants to provide the same result as 32-bit
  ones, IMAGE_RESOURCE_DATA_ENTRY.OffsetToData fields pointing to 
  .rsrc+0x70 and .rsrc+0xA0 when loaded to memory.

Toolset Builds and Platforms:
  binutils 2.38-4ubuntu2.3
  binutils-mingw-w64-i686 2.38-3ubuntu1+9build1
  binutils-mingw-w64-x86-64 2.38-3ubuntu1+9build1
  on x86_64 Ubuntu 22.04 LTS (Linux 5.15)

-- 
You are receiving this mail because:
You are on the CC list for the bug.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]