This is an archive of the discontinued LLVM Phabricator instance.

Align SHT_NOBITS sections is they are the first on a PT_LOAD
ClosedPublic

Authored by rafael on Dec 29 2017, 2:01 PM.

Details

Summary

We normally want to ignore SHT_NOBITS sections when computing offsets. The sh_offset of section itself seems to be irrelevant and

  • If the section is in the middle of a PT_LOAD, it will make no difference on the computed offset of the followup section.
  • If it is in the end of a PT_LOAD, we want to avoid its alignment changing the offset of the followup sections.

The issue is if it is at the start of the PT_LOAD. In that case we do have to align it so that the following sections have congruent address and offset module the page size. We were not handling this case.

This should fix freebsd kernel link.

Diff Detail

Event Timeline

rafael created this revision.Dec 29 2017, 2:01 PM
dim added a comment.Dec 29 2017, 3:26 PM

This makes libelf (and thus ctfmerge and elftoolchain objcopy) accept the lld-linked kernel, and building succeeds. GNU objcopy still shows that it is adjusting sections:

$ /usr/local/bin/objcopy /usr/obj/share/dim/src/freebsd/clang600-import/amd64.amd64/sys/GENERIC/kernel.full kernel.test
/usr/local/bin/objcopy: kernel.test: section .init_array lma 0x1734000 adjusted to 0x17340f0
/usr/local/bin/objcopy: kernel.test: section .fini_array lma 0x1734000 adjusted to 0x17340f0
/usr/local/bin/objcopy: kernel.test: section .data.rel.ro lma 0x1734000 adjusted to 0x17340f0
/usr/local/bin/objcopy: kernel.test: section .preinit_array lma 0x1734000 adjusted to 0x17340f0

However, that may be some quirk of GNU binutils's ELF handling...

dim added a comment.Dec 29 2017, 4:49 PM

It looks like GNU bfd/elf.c looks at the MemSiz field in the program header, then adds that to PhysAddr to get the end address of the segment (see line 5541 in bfd/elf.c). In case of .init_array, .fini_array, .data.rel.ro and .preinit_array, the load address is before the end of the address, and that causes it to complain:

$ readelf -lSW /usr/obj/share/dim/src/freebsd/clang600-import/amd64.amd64/sys/GENERIC/kernel.full
There are 68 section headers, starting at offset 0x642dc08:

Section Headers:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
  [ 1] .interp           PROGBITS        ffffffff80200270 000270 00000d 00   A  0   0  1
  [ 2] .hash             HASH            ffffffff80200280 000280 029088 04   A  4   0  4
  [ 3] .gnu.hash         GNU_HASH        ffffffff80229308 029308 021a44 00   A  4   0  8
  [ 4] .dynsym           DYNSYM          ffffffff8024ad50 04ad50 07b180 18   A  5   1  8
  [ 5] .dynstr           STRTAB          ffffffff802c5ed0 0c5ed0 065c45 00   A  0   0  1
  [ 6] .text             PROGBITS        ffffffff8032c000 12c000 d8a544 00  AX  0   0 4096
  [ 7] .rodata           PROGBITS        ffffffff810b6560 eb6560 6430c0 00 AMS  0   0 32
  [ 8] .eh_frame         PROGBITS        ffffffff816f9620 14f9620 028198 00   A  0   0  8
  [ 9] set_sysctl_set    PROGBITS        ffffffff817217b8 15217b8 0047f8 00   A  0   0  8
  [10] set_sysinit_set   PROGBITS        ffffffff81725fb0 1525fb0 003340 00   A  0   0  8
  [11] set_sysuninit_set PROGBITS        ffffffff817292f0 15292f0 001840 00   A  0   0  8
  [12] set_modmetadata_set PROGBITS        ffffffff8172ab30 152ab30 003210 00   A  0   0  8
  [13] set_cam_xpt_xport_set PROGBITS        ffffffff8172dd40 152dd40 000058 00   A  0   0  8
  [14] set_cam_xpt_proto_set PROGBITS        ffffffff8172dd98 152dd98 000028 00   A  0   0  8
  [15] set_kdb_dbbe_set  PROGBITS        ffffffff8172ddc0 152ddc0 000018 00   A  0   0  8
  [16] set_ah_chips      PROGBITS        ffffffff8172ddd8 152ddd8 000048 00   A  0   0  8
  [17] set_ah_rfs        PROGBITS        ffffffff8172de20 152de20 000050 00   A  0   0  8
  [18] set_kbddriver_set PROGBITS        ffffffff8172de70 152de70 000020 00   A  0   0  8
  [19] set_sdt_providers_set PROGBITS        ffffffff8172de90 152de90 0000a8 00   A  0   0  8
  [20] set_sdt_probes_set PROGBITS        ffffffff8172df38 152df38 0010c0 00   A  0   0  8
  [21] set_sdt_argtypes_set PROGBITS        ffffffff8172eff8 152eff8 003348 00   A  0   0  8
  [22] set_cons_set      PROGBITS        ffffffff81732340 1532340 000030 00   A  0   0  8
  [23] set_gdb_dbgport_set PROGBITS        ffffffff81732370 1532370 000010 00   A  0   0  8
  [24] usb_host_id       PROGBITS        ffffffff81732380 1532380 000040 00   A  0   0 32
  [25] set_vt_drv_set    PROGBITS        ffffffff817323c0 15323c0 000018 00   A  0   0  8
  [28] set_ieee80211_ioctl_getset PROGBITS        ffffffff81732400 1532400 000018 00   A  0   0  8
  [29] set_ieee80211_ioctl_setset PROGBITS        ffffffff81732418 1532418 000018 00   A  0   0  8
  [30] set_scanner_set   PROGBITS        ffffffff81732430 1532430 000028 00   A  0   0  8
  [31] set_videodriver_set PROGBITS        ffffffff81732458 1532458 000020 00   A  0   0  8
  [32] set_scterm_set    PROGBITS        ffffffff81732478 1532478 000008 00   A  0   0  8
  [33] set_scrndr_set    PROGBITS        ffffffff81732480 1532480 000048 00   A  0   0  8
  [34] set_vga_set       PROGBITS        ffffffff817324c8 15324c8 000048 00   A  0   0  8
  [35] kern_conf         PROGBITS        ffffffff81732510 1532510 001025 00   A  0   0 16
  [36] .note.gnu.build-id NOTE            ffffffff81733538 1533538 000024 00   A  0   0  4
  [37] .preinit_array    NOBITS          ffffffff81734000 153355c 000000 00   A  0   0  1
  [38] .init_array       NOBITS          ffffffff81734000 153355c 000000 00   A  0   0  1
  [39] .fini_array       NOBITS          ffffffff81734000 153355c 000000 00   A  0   0  1
  [40] .data.rel.ro      NOBITS          ffffffff81734000 1534000 000000 00  WA  0   0  1
  [41] .dynamic          DYNAMIC         ffffffff81734000 1534000 0000f0 10  WA  5   0  8
  [42] .data.read_frequently PROGBITS        ffffffff81735000 1535000 000048 00  WA  0   0  8
  [43] .data.read_mostly PROGBITS        ffffffff81735048 1535048 000129 00  WA  0   0  8
  [44] .data.exclusive_cache_line PROGBITS        ffffffff81735180 1535180 006bc0 00  WA  0   0 64
  [45] .data             PROGBITS        ffffffff8173bd40 153bd40 140ccc 00  WA  0   0 64
  [46] set_pcpu          PROGBITS        ffffffff8187ca40 167ca40 001038 00  WA  0   0 64
  [47] set_vnet          PROGBITS        ffffffff8187da80 167da80 008948 00  WA  0   0 16
  [48] .bss              NOBITS          ffffffff81886400 16863c8 52a518 00  WA  0   0 128
  [49] .ldata            NOBITS          ffffffff81db1918 16863c8 000000 00  WA  0   0  1
  [50] .comment          PROGBITS        0000000000000000 16863c8 0230d7 00  MS  0   0  1
  [51] .debug_aranges    PROGBITS        0000000000000000 16a949f 0001b0 00      0   0  1
  [52] .debug_pubnames   PROGBITS        0000000000000000 16a964f 225c4b 00      0   0  1
  [53] .debug_info       PROGBITS        0000000000000000 18cf29a 244c8f5 00      0   0  1
  [54] .debug_abbrev     PROGBITS        0000000000000000 3d1bb8f 126540 00      0   0  1
  [55] .debug_line       PROGBITS        0000000000000000 3e420cf 74acb5 00      0   0  1
  [56] .debug_frame      PROGBITS        0000000000000000 458cd88 139760 00      0   0  8
  [57] .debug_str        PROGBITS        0000000000000000 46c64e8 2d7d40 01  MS  0   0  1
  [58] .debug_loc        PROGBITS        0000000000000000 499e228 106ed53 00      0   0  1
  [59] .debug_macinfo    PROGBITS        0000000000000000 5a0cf7b 000754 00      0   0  1
  [60] .debug_pubtypes   PROGBITS        0000000000000000 5a0d6cf 4e9610 00      0   0  1
  [61] .debug_ranges     PROGBITS        0000000000000000 5ef6cdf 1708a0 00      0   0  1
  [62] __xen_guest       PROGBITS        0000000000000000 606757f 000000 00      0   0  1
  [63] .note.Xen         NOTE            0000000000000000 6067580 0001a0 00      0   0  4
  [64] .shstrtab         STRTAB          0000000000000000 61d54e0 00039d 00      0   0  1
  [65] .SUNW_ctf         PROGBITS        0000000000000000 6360fcc 0ccc37 00     66   0  4
  [66] .symtab           SYMTAB          0000000000000000 6067720 16ddc0 18     67 41433  8
  [67] .strtab           STRTAB          0000000000000000 61d587d 18b74c 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)

Elf file type is EXEC (Executable file)
Entry point 0xffffffff8032c000
There are 10 program headers, starting at offset 64

Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  PHDR           0x000040 0xffffffff80200040 0xffffffff80200040 0x000230 0x000230 R   0x8
  INTERP         0x000270 0xffffffff80200270 0x0000000000200270 0x00000d 0x00000d R   0x1
      [Requesting program interpreter: /red/herring]
  LOAD           0x000000 0xffffffff80200000 0xffffffff80200000 0x000270 0x000270 R E 0x1000
  LOAD           0x000270 0xffffffff80200270 0x0000000000200270 0x15332ec 0x1533d90 R E 0x1000
  LOAD           0x1534000 0xffffffff81734000 0x0000000001734000 0x1523c8 0x67d918 RW  0x1000
  DYNAMIC        0x1534000 0xffffffff81734000 0x0000000001734000 0x0000f0 0x0000f0 RW  0x8
  GNU_RELRO      0x1534000 0xffffffff81734000 0x0000000001734000 0x0000f0 0x0000f0 R   0x1
  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0
  NOTE           0x1533538 0xffffffff81733538 0x0000000001733538 0x000024 0x000024 R   0x4
  NOTE           0x85400f8 0x0000000000000000 0x0000000080000000 0x000000 0x000000 R   0x4

 Section to Segment mapping:
  Segment Sections...
   00
   01     .interp
   02
   03     .interp .hash .gnu.hash .dynsym .dynstr .text .rodata .eh_frame set_sysctl_set set_sysinit_set set_sysuninit_set set_modmetadata_set set_cam_xpt_xport_set set_cam_xpt_proto_set set_kdb_dbbe_s
et set_ah_chips set_ah_rfs set_kbddriver_set set_sdt_providers_set set_sdt_probes_set set_sdt_argtypes_set set_cons_set set_gdb_dbgport_set usb_host_id set_vt_drv_set set_ratectl_set set_crypto_set set
_ieee80211_ioctl_getset set_ieee80211_ioctl_setset set_scanner_set set_videodriver_set set_scterm_set set_scrndr_set set_vga_set kern_conf .note.gnu.build-id
   04     .preinit_array .init_array .fini_array .data.rel.ro .dynamic .data.read_frequently .data.read_mostly .data.exclusive_cache_line .data set_pcpu set_vnet .bss
   05     .dynamic
   06     .preinit_array .init_array .fini_array .data.rel.ro .dynamic
   07
   08     .note.gnu.build-id
   09

Here .preinit_array .init_array .fini_array .data.rel.ro .dynamic are both in the LOAD and GNU_RELRO segments, but in the relro one its MemSiz is 0xf0, which is exactly the amount that BFD objcopy is adjusting it with.

dim accepted this revision.Jan 1 2018, 2:41 PM

For me, this works fine. Further reviews would be appreciated :)

This revision is now accepted and ready to land.Jan 1 2018, 2:41 PM
emaste accepted this revision.Jan 11 2018, 7:37 PM

Seems fine to me

espindola accepted this revision.Jan 12 2018, 9:44 AM
espindola added a subscriber: espindola.

r321657.

dim closed this revision.Jan 13 2018, 10:48 AM

This has been committed as rL321657, closing.