Page 1 of 1
Find PE image (No PDB) error
Posted: Thu Aug 11, 2016 10:36 am
by chris13524
I'm just getting started with UEFI, I followed the little "tutorial" on with wiki:
http://wiki.osdev.org/UEFI
Code: Select all
#include <efi.h>
#include <efilib.h>
extern "C" EFI_STATUS EFIAPI efi_main(EFI_HANDLE ImageHandle,
EFI_SYSTEM_TABLE *SystemTable) {
InitializeLib(ImageHandle, SystemTable);
Print((CHAR16*) "Hello world!");
while (true) {
}
return EFI_SUCCESS;
}
To make this work for C++, I added the extern "C" thing to efi_main (and updated the extension). However, when I compiled it, I got this error:
Code: Select all
src/boot/uefi.cpp: In function ‘EFI_STATUS efi_main(EFI_HANDLE, EFI_SYSTEM_TABLE*)’:
src/boot/uefi.cpp:16:23: error: invalid conversion from ‘const wchar_t*’ to ‘CHAR16* {aka short unsigned int*}’ [-fpermissive]
Print(L"Hello world!");
^
In file included from src/boot/uefi.cpp:9:0:
gnu-efi/headers/efilib.h:404:1: note: initializing argument 1 of ‘UINTN Print(CHAR16*, ...)’
Print (
^
I made a blind attempt at fixing this and removed the "L" and casted my string to CHAR16*. This seemed to compile fine, but when I ran it, I got a crash:
Code: Select all
!!!! X64 Exception Type - 0000000000000006 CPU Apic ID - 00000000 !!!!
RIP - 0000000006764030, CS - 0000000000000028, RFLAGS - 0000000000000292
RAX - 0000000006772E98, RCX - 0000000000000000, RDX - 0000000007F21F18
RBX - 0000000007F21F18, RSP - 0000000007F94B40, RBP - 0000000007F94B60
RSI - 0000000007F21F1C, RDI - 0000000006772E9A
R8 - 0000000000000000, R9 - 0000000007D4DF18, R10 - 0000000006EF3F60
R11 - 0000000006EFCE30, R12 - 0000000000000000, R13 - 0000000000000000
R14 - 0000000000000000, R15 - 0000000000000000
DS - 0000000000000008, ES - 0000000000000008, FS - 0000000000000008
GS - 0000000000000008, SS - 0000000000000008
CR0 - 0000000080000033, CR2 - 0000000000000000, CR3 - 0000000007F33000
CR4 - 0000000000000668, CR8 - 0000000000000000
DR0 - 0000000000000000, DR1 - 0000000000000000, DR2 - 0000000000000000
DR3 - 0000000000000000, DR6 - 00000000FFFF0FF0, DR7 - 0000000000000400
GDTR - 0000000007F1CE98 000000000000003F, LDTR - 0000000000000000
IDTR - 0000000007C07018 0000000000000FFF, TR - 0000000000000000
FXSAVE_STATE - 0000000007F947A0
!!!! Find PE image (No PDB) (ImageBase=000000000675F000, EntryPoint=0000000006761038) !!!!
If I remove InitializeLib and Print (leaving the while(true){} loop), it hangs (as expected).
I try to distance myself from Microsoft, so I'm not familiar with the calling conventions. I'm assuming that's what the problem is.
To make sure it's not a problem with building, I directly copied the tutorial. It seems to work fine (printing "Hello, World!"), but as soon as I try to switch to C++, I get these errors.
Thanks!
Re: Find PE image (No PDB) error
Posted: Thu Aug 11, 2016 11:52 am
by heat
Compiler? Target? Command line options? Also I'm not sure that UEFI's API is compatible with C++.
Re: Find PE image (No PDB) error
Posted: Thu Aug 11, 2016 12:03 pm
by chris13524
I'm not sure that UEFI's API is compatible with C++.
This guy appears to be using C++:
http://forum.osdev.org/viewtopic.php?f=1&t=29720 https://github.com/kiznit/rainbow-os/bl ... fiboot.cpp
Here's my build script:
Code: Select all
build/boot/uefi.o: src/boot/uefi.cpp | build/boot/.dirstamp
gcc src/boot/uefi.cpp \
-c \
-fno-stack-protector \
-fpic \
-fshort-wchar \
-mno-red-zone \
-I gnu-efi/headers \
-I gnu-efi/headers/x86_64 \
-DEFI_FUNCTION_WRAPPER \
-o build/boot/uefi.o
build/uefi.so: build/boot/uefi.o | build/.dirstamp
ld build/boot/uefi.o \
gnu-efi/crt0-efi-x86_64.o \
-nostdlib \
-znocombreloc \
-T gnu-efi/elf_x86_64_efi.lds \
-shared \
-Bsymbolic \
-L gnu-efi/libs \
-l:libgnuefi.a \
-l:libefi.a \
-o build/uefi.so
build/aura.efi: build/uefi.so | build/.dirstamp
objcopy -j .text \
-j .sdata \
-j .data \
-j .dynamic \
-j .dynsym \
-j .rel \
-j .rela \
-j .reloc \
--target=efi-app-x86_64 \
build/uefi.so \
build/aura.efi
# ---- output files ----
.PHONY:
img: build/aura.img
build/aura.img: build/aura.efi | build/.dirstamp
dd if=/dev/zero of=build/aura.img bs=512 count=93750 # allocate disk
parted build/aura.img -s -a minimal mklabel gpt # make gpt table
parted build/aura.img -s -a minimal mkpart EFI FAT16 2048s 93716s # make EFI partition
parted build/aura.img -s -a minimal toggle 1 boot # make it bootable
dd if=/dev/zero of=/tmp/part.img bs=512 count=91669 # allocate partition
mformat -i /tmp/part.img -h 32 -t 32 -n 64 -c 1 # format partition
if [ -d "build/img_root" ]; then rm -r build/img_root; fi
# build FS structure
mkdir build/img_root
mkdir build/img_root/EFI
mkdir build/img_root/EFI/BOOT
cp build/aura.efi build/img_root/EFI/BOOT/BOOTX64.efi # hard coded file name and path
mcopy -s -i /tmp/part.img build/img_root/* :: # copy FS to partition
dd if=/tmp/part.img of=build/aura.img bs=512 count=91669 seek=2048 conv=notrunc # copy parition to disk
rm /tmp/part.img # remove tmp partition file
Re: Find PE image (No PDB) error
Posted: Thu Aug 11, 2016 12:07 pm
by heat
chris13524 wrote:I'm not sure that UEFI's API is compatible with C++.
This guy appears to be using C++:
http://forum.osdev.org/viewtopic.php?f=1&t=29720 https://github.com/kiznit/rainbow-os/bl ... fiboot.cpp
Here's my build script:
Code: Select all
build/boot/uefi.o: src/boot/uefi.cpp | build/boot/.dirstamp
gcc src/boot/uefi.cpp \
-c \
-fno-stack-protector \
-fpic \
-fshort-wchar \
-mno-red-zone \
-I gnu-efi/headers \
-I gnu-efi/headers/x86_64 \
-DEFI_FUNCTION_WRAPPER \
-o build/boot/uefi.o
build/uefi.so: build/boot/uefi.o | build/.dirstamp
ld build/boot/uefi.o \
gnu-efi/crt0-efi-x86_64.o \
-nostdlib \
-znocombreloc \
-T gnu-efi/elf_x86_64_efi.lds \
-shared \
-Bsymbolic \
-L gnu-efi/libs \
-l:libgnuefi.a \
-l:libefi.a \
-o build/uefi.so
build/aura.efi: build/uefi.so | build/.dirstamp
objcopy -j .text \
-j .sdata \
-j .data \
-j .dynamic \
-j .dynsym \
-j .rel \
-j .rela \
-j .reloc \
--target=efi-app-x86_64 \
build/uefi.so \
build/aura.efi
# ---- output files ----
.PHONY:
img: build/aura.img
build/aura.img: build/aura.efi | build/.dirstamp
dd if=/dev/zero of=build/aura.img bs=512 count=93750 # allocate disk
parted build/aura.img -s -a minimal mklabel gpt # make gpt table
parted build/aura.img -s -a minimal mkpart EFI FAT16 2048s 93716s # make EFI partition
parted build/aura.img -s -a minimal toggle 1 boot # make it bootable
dd if=/dev/zero of=/tmp/part.img bs=512 count=91669 # allocate partition
mformat -i /tmp/part.img -h 32 -t 32 -n 64 -c 1 # format partition
if [ -d "build/img_root" ]; then rm -r build/img_root; fi
# build FS structure
mkdir build/img_root
mkdir build/img_root/EFI
mkdir build/img_root/EFI/BOOT
cp build/aura.efi build/img_root/EFI/BOOT/BOOTX64.efi # hard coded file name and path
mcopy -s -i /tmp/part.img build/img_root/* :: # copy FS to partition
dd if=/tmp/part.img of=build/aura.img bs=512 count=91669 seek=2048 conv=notrunc # copy parition to disk
rm /tmp/part.img # remove tmp partition file
I might be confused, but didn't gnuefi handle elf relocation? Try not running the objcopy and see how it goes.
Re: Find PE image (No PDB) error
Posted: Thu Aug 11, 2016 12:14 pm
by chris13524
I might be confused, but didn't gnuefi handle elf relocation? Try not running the objcopy and see how it goes.
I think you need the objcopy. I removed that and executed the output of ld. I even revered back to C and tried it. It said it couldn't boot, like it didn't exist:
Code: Select all
Boot Failed. EFI DVD/CDROM
Boot Failed. EFI Floppy
Boot Failed. EFI Floppy 1
Boot Failed. EFI Hard Drive
Re: Find PE image (No PDB) error
Posted: Thu Aug 11, 2016 1:58 pm
by Octocontrabass
You're including C headers as if they were C++ headers.
Maybe try doing this instead:
Code: Select all
extern "C" {
#include <efi.h>
#include <efilib.h>
}
Re: Find PE image (No PDB) error
Posted: Thu Aug 11, 2016 2:12 pm
by chris13524
Octocontrabass wrote:You're including C headers as if they were C++ headers.
Maybe try doing this instead:
Code: Select all
extern "C" {
#include <efi.h>
#include <efilib.h>
}
Ah, this fixed most of my problems. I had to re-enable objcopy as well.
Now it's printing "Hlowrd". I'm assuming that is because I'm casting to CHAR16* when it should be CHAR8* ? I'm guessing that's what the "L" did, make it a 16 bit literal? But again, my compiler is not understanding that "L".
Re: Find PE image (No PDB) error
Posted: Thu Aug 11, 2016 2:15 pm
by chris13524
Note: I'm not using the standard library.
Re: Find PE image (No PDB) error
Posted: Thu Aug 11, 2016 2:33 pm
by Octocontrabass
That's probably something to do with const-correctness. If gnu-efi is wrong and Print() should be able to take a pointer to const as input, a const_cast will silence the warning.
Re: Find PE image (No PDB) error
Posted: Thu Aug 11, 2016 5:55 pm
by heat
Is Print() supposed to take a CHAR16* or a CHAR8*? Stuff like that matters a lot, especially when CHAR16 is unicode and CHAR8 isn't.
Re: Find PE image (No PDB) error
Posted: Thu Aug 11, 2016 6:24 pm
by chris13524
heat wrote:Is Print() supposed to take a CHAR16* or a CHAR8*? Stuff like that matters a lot, especially when CHAR16 is unicode and CHAR8 isn't.
This is exactly the issue, I'm not sure how to make 16-bit string literals though.
Re: Find PE image (No PDB) error
Posted: Thu Aug 11, 2016 6:57 pm
by ~
When you start writing a program, start by the skeleton. If it doesn't run with an empty main, then the problem is in the toolchain usage and stages earlier than compilation, or in the structure of the base skeleton.
To use wide chars that adjust automatically to the maximum width, use wchar_t
You can also use char8_t, uchar8_t, char16_t, uchar16_t, char32_t, uchar32_t or similar types for signed and unsigned 8, 16 and 32-bit characters selected in an explicit way.
Re: Find PE image (No PDB) error
Posted: Fri Aug 12, 2016 2:04 am
by Octocontrabass
chris13524 wrote:Now it's printing "Hlowrd". I'm assuming that is because I'm casting to CHAR16* when it should be CHAR8* ? I'm guessing that's what the "L" did, make it a 16 bit literal? But again, my compiler is not understanding that "L".
The problem is that Print() is defined as taking a CHAR16*, but it should have been defined to take a
const CHAR16*. This doesn't matter for C, but it causes the "invalid conversion" error in C++.
You can fix it like this:
Code: Select all
Print(const_cast<CHAR16*>(L"Hello world!"));
(...But why isn't there an error when you convert from const char*?)