Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for binutils >= 2.36 #155

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

lorenzo-stoakes
Copy link

As-is trying to build with binutils 2.36 and a recent gcc is problematic in 2 ways:

  1. It fails to boot in qemu, getting stuck in a bootloop at 'Booting from Hard Disk..'
  2. fs.img fails to build due to an overzealous -Wstringop-overflow error in usertests.c combined with -Werror

This PR resolves both issues, firstly by stripping the newly introduced '.note.gnu.property' section introduced by binutils 2.36 which appears to be the source of the problem and secondly suppressing the -Wstringop-overflow warning in usertests.c.

The PR also strips some trailing space in the Makefile as trailing space is indeed, the devil.

@Miracle-1996
Copy link

Thanks a lot! However I don’t know what happened. What should I do to understand the differences?

@lorenzo-stoakes
Copy link
Author

It looks like the ELF loader is assuming that this section is not present, from binutils 2.36 on it gets added by default which causes the system to fail to be able to correctly load userland binaries. The solution is to simply remove the section altogether. Of course an alternative might be to adjust the loader code.

I left this PR here not only in case a maintainer (though I realise the x86 version is no longer maintained) decided to merge but more so that somebody else who found xv6 broken could use this PR to fix things locally :)

@Miracle-1996
Copy link

Yeah! I encounter the problem today when I compile this project in my Arch-Linux with binutils 2.36.1-3.

@lorenzo-stoakes
Copy link
Author

arch is the key motivator for this change as it is the distro I use. If you try this it should sort out the issue.

@Miracle-1996
Copy link

Miracle-1996 commented Aug 17, 2021

Yes!Thanks a lot again! Actually the version which I compiled is the rev9. Today I compile it with "make qemu-nox" in the arch-linux rather than the ubuntu 18.04 which I used to use. I deleted the "Werror" in CFLAGS to deal with the "-Werror=stringop-overflow=". Then it compiles well. However it hang over in the "Booting From Hard Disk“. After I revising the Makefile according to your's file and the #115.,it works well!

@officialcjunior
Copy link

I left this PR here not only in case a maintainer (though I realise the x86 version is no longer maintained) decided to merge but more so that somebody else who found xv6 broken could use this PR to fix things locally :)

Thanks for the PR. I fetched from your branch to make it work on Arch Linux. :)

@McBride-SallyJoeBob
Copy link

Thank You!!! hopefully they merge this PR soon!

budde25 added a commit to budde25/xv6-public that referenced this pull request Dec 31, 2021
lxgxl added a commit to lxgxl/xv6-public that referenced this pull request Mar 24, 2022
1)
binutils>=2.36
mit-pdos#155
2)
-Wstringop-overflow error in usertests.c

Add:
1)
.clangd
saza-ku added a commit to saza-ku/xv6-public that referenced this pull request Oct 29, 2022
- add devcontainer config
- fix boot process (ref:
  mit-pdos#155)
@CodingKoopa
Copy link

CodingKoopa commented Feb 25, 2023

I think I understand why this is necessary. First, a small isolated testcase:
$ cat initcode.c

void start() {
  return;
}

$ cat Makefile

CFLAGS = -m32 -march=i386
LDFLAGS = -m elf_i386

initcode: initcode.o
        $(LD) $(LDFLAGS) -N -e start -o $@ $<

initcode.o: initcode.c
        $(CC) $(CFLAGS) -c $<

In this case where we leave the addresses as their defaults, we can see that ld places .note.gnu.property before .text:
$ readelf -S initcode

There are 9 section headers, starting at offset 0x2a4:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .note.gnu.pr[...] NOTE            080480b4 0000b4 000028 00   A  0   0  4
  [ 2] .text             PROGBITS        080480dc 0000dc 000021 00 WAX  0   0  1
  [ 3] .eh_frame         PROGBITS        08048100 000100 00004c 00   A  0   0  4
  [ 4] .got.plt          PROGBITS        0804814c 00014c 00000c 04  WA  0   0  4
  [ 5] .comment          PROGBITS        00000000 000158 00001b 01  MS  0   0  1
  [ 6] .symtab           SYMTAB          00000000 000174 000090 10      7   4  4
  [ 7] .strtab           STRTAB          00000000 000204 000050 00      0   0  1
  [ 8] .shstrtab         STRTAB          00000000 000254 000050 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),
  D (mbind), p (processor specific)

The sections start around 0x08048000, which is the arbitrary location used as the default start location for .text. [1]

When we do specify the address of the .text section, only it and sections after it will be placed at the beginning of the output file. Therefore, .note.gnu.property will remain wherever it was before. [2]
$ ld -m elf_i386 -N -e start -Ttext 0 -o initcode initcode.o
$ readelf -S initcode

There are 9 section headers, starting at offset 0x2b4:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .note.gnu.pr[...] NOTE            080480d4 000140 000028 00   A  0   0  4
  [ 2] .text             PROGBITS        00000000 0000d4 000014 00 WAX  0   0  1
  [ 3] .eh_frame         PROGBITS        00000014 0000e8 00004c 00   A  0   0  4
  [ 4] .got.plt          PROGBITS        00000060 000134 00000c 04  WA  0   0  4
  [ 5] .comment          PROGBITS        00000000 000168 00001b 01  MS  0   0  1
  [ 6] .symtab           SYMTAB          00000000 000184 000090 10      7   4  4
  [ 7] .strtab           STRTAB          00000000 000214 000050 00      0   0  1
  [ 8] .shstrtab         STRTAB          00000000 000264 000050 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),
  D (mbind), p (processor specific)

Then, because of that far-out section, when we convert the initcode to a binary, rather than getting a nice and small 44 (!) byte binary, we get a 16+ MiB binary which would take ages for the ELF loader to load from the image. To get an idea of how long it takes, I modified the bootloader to output progress over serial, and the answer is long.


Understanding this, let's explore our options for how to fix it. Deleting the .note.gnu.property section is a satisfactory solution, but I am interested in alternative solutions since the issue is not the existence of that section, but rather the location of it.

Unfortunately, the ld command line does not allow us to specify a "general" start address for our binary. It will only let us fix the start addresses of specific sections, such as .text or .note.gnu.property. Of course, fixing the address of the latter would not be a good solution because it would not be compatible with earlier versions of binutils, and does not clearly express our intent.

I think that the cleanest solution is to write a super small linker script that fixes .text to the beginning of the output file. While we are at it, we can also link directly into the binary format (this should also be applicable for earleir binutils).

Makefile

...
initcode: initcode.S
	$(CC) $(CFLAGS) -nostdinc -I. -c initcode.S
	$(LD) $(LDFLAGS) -T initcode.ld -o initcode -N initcode.o
	$(OBJDUMP) -S initcode.o > initcode.asm
...

initcode.ld

OUTPUT_FORMAT("binary")
ENTRY(start)

SECTIONS
{
    .text : {
        *(.text)
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants