How can I force UEFI to zero my PE BSS section?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
cptroot
Posts: 4
Joined: Wed Apr 13, 2016 10:23 pm
Libera.chat IRC: cptroot

How can I force UEFI to zero my PE BSS section?

Post by cptroot »

I'm currently writing a UEFI based operating system using Rust. This means that it's generating LLVM IR, and then compiling that down to ASM, before I link it with a bare bones C entry point.

My question is:
How do I force the BSS to be zeroed before my UEFI Loader starts executing? Currently Rust is making an optimization by having a mutex that starts initialized to all zeroes live in .bss, but when my program loads i'm instead getting garbage.

If I ask the compiler to make the object start with a struct of {0u8, 1u8}, I can see that it is correct when the program loads. If instead I ask it to start with {0u8, 0u8}, the memory is filled with 0xafafafaf. When I examine the objdump of the library, I can see the following:

Code: Select all

objdump -t kernel/target/x86_64-unknown-pintos/debug/libkernel.a | ag WRITER
0000000000000000 l     O .bss._ZN6kernel6serial13SERIAL_WRITER17h796764bd9f75b31cE	0000000000000002 _ZN6kernel6serial13SERIAL_WRITER17h796764bd9f75b31cE
0000000000000000 l    d  .bss._ZN6kernel6serial13SERIAL_WRITER17h796764bd9f75b31cE	0000000000000000 .bss._ZN6kernel6serial13SERIAL_WRITER17h796764bd9f75b31cE
Does anyone know how to force 0-initialization for .bss sections when loading your program under UEFI?
User avatar
Velko
Member
Member
Posts: 153
Joined: Fri Oct 03, 2008 4:13 am
Location: Ogre, Latvia, EU

Re: How can I force UEFI to zero my PE BSS section?

Post by Velko »

Or you can zero the .bss section yourself in startup code. Few lines of assembly to solve the issue regardless of bootloader.
If something looks overcomplicated, most likely it is.
alexfru
Member
Member
Posts: 1112
Joined: Tue Mar 04, 2014 5:27 am

Re: How can I force UEFI to zero my PE BSS section?

Post by alexfru »

The question is, is the .bss section somehow mentioned in your PE at all and if not why? Is it in there as a separate section that's appropriately marked as uninitialized? Is it in there as a trailing part of an initialized data section (if a section's memory size is greater than its file size the rest of the section should be zeroed by the loader)? Is there a linker script that somehow omits the .bss section or somehow throws its "contents" away?
cptroot
Posts: 4
Joined: Wed Apr 13, 2016 10:23 pm
Libera.chat IRC: cptroot

Re: How can I force UEFI to zero my PE BSS section?

Post by cptroot »

Ah! Y'all are correct. My linker script is somehow causing problems with my .bss.

I'm using the standard gnu-efi /usr/lib/elf_x86_64_efi.lds, and although it has this line in it:

Code: Select all

 13  . = ALIGN(4096);
 12   .data :
 11   {
 10    *(.rodata*)
  9    *(.got.plt)
  8    *(.got)
  7    *(.data*)
  6    *(.sdata)
  5    /* the EFI loader doesn't seem to like a .bss section, so we stick
  4       it all into .data: */
  3    *(.sbss)
  2    *(.scommon)
  1    *(.dynbss)
40     *(.bss)                                                                
  1    *(COMMON)
  2    *(.rel.local)
  3   }
that seems to say that the .bss should be stored in the .data section, the resulting .so still has a .bss section:

Code: Select all

objdump -h main.so

main.so:     file format elf64-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .hash         000020cc  0000000000000000  0000000000000000  00200000  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .eh_frame     000092d8  0000000000003000  0000000000003000  00203000  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .text         0002a65a  000000000000d000  000000000000d000  0020d000  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  3 .plt          00000030  0000000000037660  0000000000037660  00237660  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  4 .reloc        0000000a  0000000000038000  0000000000038000  00238000  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .data         0000a290  0000000000039000  0000000000039000  00239000  2**5
                  CONTENTS, ALLOC, LOAD, DATA
  6 .dynamic      00000130  0000000000044000  0000000000044000  00244000  2**3
                  CONTENTS, ALLOC, LOAD, DATA
  7 .dynsym       000063f0  000000000004a000  000000000004a000  0024a000  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  8 .rela         00004770  0000000000045000  0000000000045000  00245000  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  9 .rela.plt     00000030  0000000000049770  0000000000049770  00249770  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 10 .dynstr       00011d2a  0000000000051000  0000000000051000  00251000  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 11 .gcc_except_table 00000300  0000000000063000  0000000000063000  00263000  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 12 .debug_gdb_scripts 00000088  0000000000063300  0000000000063300  00263300  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 13 .bss._ZN6kernel9interrupt18interrupt_handlers17h15f61b7695ab7ad8E 00000800  0000000000063388  0000000000063388  00263388  2**3
                  ALLOC
 14 .bss._ZN6kernel9interrupt3idt3idt17h2a14c81f6e09e258E 00001000  0000000000063b88  0000000000063b88  00263388  2**2
                  ALLOC
 15 .bss._ZN6kernel6serial13SERIAL_WRITER17h796764bd9f75b31cE 00000002  0000000000064b88  0000000000064b88  00263388  2**0
                  ALLOC
 16 .comment      00000056  0000000000000000  0000000000000000  00263388  2**0
                  CONTENTS, READONLY
 17 .debug_info   0000fa9f  0000000000000000  0000000000000000  002633de  2**0
                  CONTENTS, READONLY, DEBUGGING
 18 .debug_abbrev 000008b0  0000000000000000  0000000000000000  00272e7d  2**0
                  CONTENTS, READONLY, DEBUGGING
 19 .debug_aranges 00000060  0000000000000000  0000000000000000  0027372d  2**0
                  CONTENTS, READONLY, DEBUGGING
 20 .debug_line   000040f2  0000000000000000  0000000000000000  0027378d  2**0
                  CONTENTS, READONLY, DEBUGGING
 21 .debug_str    00007c00  0000000000000000  0000000000000000  0027787f  2**0
                  CONTENTS, READONLY, DEBUGGING
 22 .debug_ranges 00002860  0000000000000000  0000000000000000  0027f47f  2**0
                  CONTENTS, READONLY, DEBUGGING
 23 .debug_macinfo 00000004  0000000000000000  0000000000000000  00281cdf  2**0
                  CONTENTS, READONLY, DEBUGGING
 24 .debug_pubnames 000020dd  0000000000000000  0000000000000000  00281ce3  2**0
                  CONTENTS, READONLY, DEBUGGING
 25 .debug_pubtypes 00002c48  0000000000000000  0000000000000000  00283dc0  2**0
                  CONTENTS, READONLY, DEBUGGING
Here's the line in my makefile I'm using to compile the .so:

Code: Select all

 14 target/release/main.so: main.o target/release/gdb_stub.o $(KERNEL_LIB)
 13     ld main.o target/release/gdb_stub.o $(KERNEL_LIB)       \
 12         /usr/lib/crt0-efi-x86_64.o          \
 11         -nostdlib                           \
 10         -znocombreloc                       \
  9         -T /usr/lib/elf_x86_64_efi.lds      \
  8         -shared                             \
  7         -Bsymbolic                          \
  6         -L /usr/lib                         \
  5         -l:libgnuefi.a                      \
  4         -l:libefi.a                         \
  3         -o target/release/main.so
Any thoughts?
simeonz
Member
Member
Posts: 360
Joined: Fri Aug 19, 2016 10:28 pm

Re: How can I force UEFI to zero my PE BSS section?

Post by simeonz »

Try changing the bss line in the script to:

Code: Select all

*(.bss .bss.*)
The .bss sections that remain are supposed to merge into one .bss section during the final link, but the custom script lacks the logic.

This is "vague linking" or "identical COMDAT folding" (see here). With this approach inline function definitions and template instantiations are deduplicated. The same goes for dead code elimination at link time, if it is enabled. The functions and data can be removed if traversal of the relocation references between their individual sections indicates they are unreachable. The latter is for the final link only.
cptroot
Posts: 4
Joined: Wed Apr 13, 2016 10:23 pm
Libera.chat IRC: cptroot

Re: How can I force UEFI to zero my PE BSS section?

Post by cptroot »

That worked like a charm! Thanks so much for the help.
Post Reply