diff --git a/Make.defaults b/Make.defaults index b0ae8a2..fefd194 100755 --- a/Make.defaults +++ b/Make.defaults @@ -132,12 +132,13 @@ EXPORT_LDFLAGS ?= ifeq ($(ARCH),ia64) EXPORT_CFLAGS += -mfixed-range=f32-f127 + EXPORT_LDFLAGS += -m elf64_ia64 ARCH_ALIASES = endif ifeq ($(ARCH),ia32) EXPORT_CFLAGS += -mno-mmx -mno-sse - EXPORT_LDFLAGS += --no-ld-generated-unwind-info + EXPORT_LDFLAGS += --no-ld-generated-unwind-info -m elf_i386 ifeq ($(HOSTARCH),x64) ARCH3264 = -m32 endif @@ -161,7 +162,7 @@ ifeq ($(ARCH),x64) endif EXPORT_CFLAGS += -mno-red-zone - EXPORT_LDFLAGS += --no-ld-generated-unwind-info + EXPORT_LDFLAGS += --no-ld-generated-unwind-info -m elf_x86_64 ifeq ($(HOSTARCH),ia32) ARCH3264 = -m64 endif @@ -178,18 +179,20 @@ endif ifeq ($(ARCH),mips64el) EXPORT_CFLAGS += -march=mips64r2 -EL - EXPORT_LDFLAGS += -EL + EXPORT_LDFLAGS += -EL -m elf64ltsmip ARCH3264 = -mabi=64 ARCH_ALIASES = endif ifeq ($(ARCH),aa64) ARCH_ALIASES = aarch64 + EXPORT_LDFLAGS += aarch64elf endif ifeq ($(ARCH),arm) ARCH_ALIASES = armv6 armv7 EXPORT_CFLAGS += -marm + EXPORT_LDFLAGS += armelf_linux_eabi endif # @@ -234,7 +237,7 @@ endif ASFLAGS += $(ARCH3264) EXPORT_LDFLAGS += -nostdlib --warn-common --no-undefined --fatal-warnings \ --build-id=sha1 --no-eh-frame-hdr \ - --orphan-handling=error + --orphan-handling=place LDFLAGS += $(EXPORT_LDFLAGS) ifneq ($(ARCH),arm) diff --git a/Make.rules b/Make.rules index d04b412..36ca261 100644 --- a/Make.rules +++ b/Make.rules @@ -35,12 +35,19 @@ # %.efi: %.so - $(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel \ - -j .rela -j .rel.* -j .rela.* -j .rel* -j .rela* \ - -j .reloc $(FORMAT) $*.so $@ + $(OBJCOPY) \ + --file-alignment 512 --section-alignment 4096 \ + -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel \ + -j .rela -j '.rel.*' -j '.rela.*' -j '.rel*' -j '.rela*' \ + -j .reloc \ + -j '.debug*' -j '.eh_frame*' -j .note.gnu.build-id \ + $(FORMAT) $*.so $@ %.efi.debug: %.so - $(OBJCOPY) $(FORMAT) $*.so $@ + $(OBJCOPY) \ + --file-alignment 512 --section-alignment 4096 \ + -j '.debug*' -j '.eh_frame*' -j .note.gnu.build-id \ + $(FORMAT) $*.so $@ %.so: %.o $(LD) $(LDFLAGS) $^ -o $@ $(LOADLIBES) diff --git a/apps/Makefile b/apps/Makefile index 8043fb1..c008460 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -45,7 +45,7 @@ LINUX_HEADERS = /usr/src/sys/build CPPFLAGS += -D__KERNEL__ -I$(LINUX_HEADERS)/include CRTOBJS = $(TOPDIR)/$(ARCH)/gnuefi/crt0-efi-$(ARCH).o -LDSCRIPT = $(TOPDIR)/gnuefi/elf_$(ARCH)_efi.lds +LDSCRIPT = $(TOPDIR)/gnuefi/efi.lds ifneq (,$(findstring FreeBSD,$(OS))) LDSCRIPT = $(TOPDIR)/gnuefi/elf_$(ARCH)_fbsd_efi.lds endif diff --git a/gnuefi/Makefile b/gnuefi/Makefile index 968ff7c..d0884ea 100644 --- a/gnuefi/Makefile +++ b/gnuefi/Makefile @@ -54,6 +54,7 @@ reloc_aa64.o: CFLAGS += -fno-jump-tables crt0.debug : crt0-efi-$(ARCH).o $(OBJCOPY) \ + --file-alignment 512 --section-alignment 4096 \ --only-keep-debug \ $(FORMAT) $^ $@ @@ -76,10 +77,10 @@ ifneq (,$(findstring FreeBSD,$(OS))) ifeq ($(ARCH),x64) @$(INSTALL) -v -m 644 $(SRCDIR)/elf_$(ARCH)_fbsd_efi.lds $(INSTALLROOT)$(LIBDIR)/gnuefi/$(ARCH)/efi.lds else - @$(INSTALL) -v -m 644 $(SRCDIR)/elf_$(ARCH)_efi.lds $(INSTALLROOT)$(LIBDIR)/gnuefi/$(ARCH)/efi.lds + @$(INSTALL) -v -m 644 $(SRCDIR)/efi.lds $(INSTALLROOT)$(LIBDIR)/gnuefi/$(ARCH)/efi.lds endif else - @$(INSTALL) -v -m 644 $(SRCDIR)/elf_$(ARCH)_efi.lds $(INSTALLROOT)$(LIBDIR)/gnuefi/$(ARCH)/efi.lds + @$(INSTALL) -v -m 644 $(SRCDIR)/efi.lds $(INSTALLROOT)$(LIBDIR)/gnuefi/$(ARCH)/efi.lds endif install_compat: install diff --git a/gnuefi/crt1.c b/gnuefi/crt1.c index d5cba07..5101b14 100644 --- a/gnuefi/crt1.c +++ b/gnuefi/crt1.c @@ -43,8 +43,8 @@ extern unsigned long _DYNAMIC; static void EFIAPI ctors(UINTN ldbase); static void EFIAPI dtors(UINTN ldbase); -extern EFI_STATUS _relocate(unsigned long ldbase, Elf_Dyn *dyn, - EFI_HANDLE image, EFI_SYSTEM_TABLE *systab); +extern EFI_STATUS EFIAPI _relocate(unsigned long ldbase, Elf_Dyn *dyn, + EFI_HANDLE image, EFI_SYSTEM_TABLE *systab); EFI_STATUS EFIAPI _start(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) @@ -156,6 +156,12 @@ static void EFIAPI dtors(UINTN ldbase) * Hand-craft a dummy .reloc section so EFI knows it's a relocatable * executable: */ +#if defined(__i386__) && 0 +__asm__(".section .reloc, \"a\", @0\n" + ".4byte 0\n" + ".4byte 0\n" + ".2byte 0\n"); +#elif 0 struct __attribute__((__packed__)) reloc @@ -166,6 +172,7 @@ struct }; struct reloc __attribute__((__section__(".reloc"))) dotreloc = {0, 10, 0}; +#endif static void __attribute__((__unused__)) @@ -189,6 +196,8 @@ printval_(EFI_SYSTEM_TABLE *systab, int size, uint64_t value) case 8: default: shift = 60; + if (!(value & 0xffffffff00000000ull)) + shift >>= 1; break; } mask = 0xfull << shift; diff --git a/gnuefi/efi.lds b/gnuefi/efi.lds new file mode 100644 index 0000000..283d86d --- /dev/null +++ b/gnuefi/efi.lds @@ -0,0 +1,96 @@ +SECTIONS +{ + . = 0; + ImageBase = .; +/* + .text 0x1000 : ALIGN(4096) + { + _text = .; + *(.init) + _start = .; + *(.text) + *(.text.*) + *(.fini) + *(.plt) + *(.plt.got) + *(.gnu.linkonce.t.*) + . = ALIGN(4096); + _etext = .; + _text_size = _etext - _text; + } +*/ + /* + * We have to have a some kind of relocations, or else the loader doesn't + * believe this is position independent, and will try to load us at e.g. + * 0x1000, which will fail. + */ + . = SIZEOF_HEADERS; + . = NEXT(4096); + .reloc ALIGN(4096) : ALIGN(4096) + { + _reloc = .; + /* + * Hand-craft a dummy .reloc entry so EFI knows it's a relocatable + * executable. + */ + LONG(0); + LONG(10); + SHORT(0); + _ereloc = .; + _reloc_size = _ereloc - _reloc; + } + + . = ALIGN(4096); + _text = ADDR(.text); + _etext = ADDR(.text) + SIZEOF(.text); + _reloc = ADDR(.reloc); + _ereloc = ADDR(.reloc) + SIZEOF(.reloc); + _data = ADDR(.data); + _edata = ADDR(.data) + SIZEOF(.data); + _bss = ADDR(.bss); + _ebss = ADDR(.bss) + SIZEOF(.bss); + _rodata = ADDR(.rodata); + _erodata = ADDR(.rodata) + SIZEOF(.rodata); + /* + _data.rel = ADDR(.data.rel); + _edata.rel = ADDR(.data.rel) + SIZEOF(.data.rel); + _data.rel.local = ADDR(.data.rel.local); + _edata.rel.local = ADDR(.data.rel.local) + SIZEOF(.data.rel.local); + */ + _data.rel.ro = ADDR(.data.rel.ro); + _edata.rel.ro = ADDR(.data.rel.ro) + SIZEOF(.data.rel.ro); + /* + _data.rel.ro.local = ADDR(.data.rel.ro.local); + _edata.rel.ro.local = ADDR(.data.rel.ro.local) + SIZEOF(.data.rel.ro.local); + */ + _dynsym = ADDR(.dynsym); + _edynsym = ADDR(.dynsym) + SIZEOF(.dynsym); + _dynstr = ADDR(.dynstr); + _edynstr = ADDR(.dynstr) + SIZEOF(.dynstr); + /* + _rel = ADDR(.rel); + _erel = ADDR(.rel) + SIZEOF(.rel); + _rela = ADDR(.rela); + _erela = ADDR(.rela) + SIZEOF(.rela); + */ + _dynamic = ADDR(.dynamic); + _edynamic = ADDR(.dynamic) + SIZEOF(.dynamic); + _eh_frame_hdr = ADDR(.eh_frame_hdr); + _eeh_frame_hdr = ADDR(.eh_frame_hdr) + SIZEOF(.eh_frame_hdr); + _eh_frame = ADDR(.eh_frame); + _eeh_frame = ADDR(.eh_frame) + SIZEOF(.eh_frame); + _note_gnu_build_id = ADDR(.note.gnu.build-id); + _enote_gnu_build_id = ADDR(.note.gnu.build-id) + SIZEOF(.note.gnu.build-id); + + /DISCARD/ : + { + *(.note.GNU-stack) + *(.GCC.command.line) + *(.gnu.version_d) + *(.gnu.version_r) + *(.gnu.version) + *(.comment) + } +} +/* INSERT BEFORE .note.gnu.build-id; */ +INSERT BEFORE .hash; diff --git a/gnuefi/elf_x64_efi.lds b/gnuefi/elf_x64_efi.lds index 1da35bd..df94270 100644 --- a/gnuefi/elf_x64_efi.lds +++ b/gnuefi/elf_x64_efi.lds @@ -2,150 +2,269 @@ OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") OUTPUT_ARCH(i386:x86-64) ENTRY(_start) +PHDRS +{ + load PT_LOAD FLAGS(7); + dynamic PT_DYNAMIC FLAGS(6); + note PT_NOTE FLAGS(4); + stack 7 FLAGS(6); +} SECTIONS { . = 0; ImageBase = .; - .text 0x2000 : ALIGN(4096) + .text 0x1000 : ALIGN(4096) { - _start = .; _text = .; + *(.init) + _start = .; *(.text) *(.text.*) + *(.fini) *(.plt) *(.plt.got) *(.gnu.linkonce.t.*) . = ALIGN(4096); - } - _etext = .; - _text_size = . - _text; + _etext = .; + _text_size = _etext - _text; + } :load /* * We have to have a some kind of relocations, or else the loader doesn't * believe this is position independent, and will try to load us at e.g. * 0x1000, which will fail. */ - . = ALIGN(4096); - .reloc : + .reloc ALIGN(4096) : ALIGN(4096) { - *(.reloc) - } + _reloc = .; + *(.reloc) + _ereloc = .; + _reloc_size = _ereloc - _reloc; + } :load - .data : ALIGN(4096) + .data ALIGN(4096) : ALIGN(4096) { - _data = .; - *(.data*) - *(.sdata) - *(.srodata*) - *(.rodata*) - *(.got.plt) - *(.got) + _data = .; + *(.data) + *(.data1) + *(.sdata) + *(.got) + *(.got.plt) + . = ALIGN(4096); + _edata = .; + _data_size = _edata - _data; + } :load - /* - * Note that these aren't the using the GNU "CONSTRUCTOR" output section - * command, so they don't start with a size. Because of p2align and the - * end/END definitions, and the fact that they're mergeable, they can also - * have NULLs which aren't guaranteed to be at the end. - */ - . = ALIGN(16); - _init_array = .; - *(SORT_BY_NAME(.init_array)) - _init_array_end = .; - __CTOR_LIST__ = .; - *(SORT_BY_NAME(.ctors)) - __CTOR_END__ = .; - __DTOR_LIST__ = .; - *(SORT_BY_NAME(.dtors)) - __DTOR_END__ = .; - _fini_array = .; - *(SORT_BY_NAME(.fini_array)) - _fini_array_end = .; - - /* the EFI loader doesn't seem to like a .bss section, so we stick - it all into .data: */ - . = ALIGN(4096); - _bss = .; - _bstart = .; - *(.sbss) - *(.scommon) - *(.dynbss) - *(.bss) - *(COMMON) - . = ALIGN(4096); - _bss_end = .; - _bend = .; - _bsize = _bend - _bstart; - } - .note.gnu.build-id : { *(.note.gnu.build-id) } - - .dynamic : ALIGN(512) { *(.dynamic) } - - .rela : + .bss ALIGN(4096) (NOLOAD) : ALIGN(4096) { - *(.rela.dyn) - *(.rela.got) - *(.rela.data) - *(.rela.data*) - *(.rela.plt) - *(.rela.text) - *(.rela.ifunc) - *(.rela.init_array) - *(.rela.fini_array) - *(.data.rela.ro.local) - *(.data.rela.local) - *(.data.rela.ro) - *(.data.rel*) - } - _edata = .; - _data_size = . - _data; + _bss = .; + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + . = ALIGN(4096); + _ebss = .; + _bss_size = _ebss - _bss; + } :load - /* - * We have to have a some kind of relocations, or else the loader doesn't - * believe this is position independent, and will try to load us at e.g. - * 0x1000, which will fail. - */ - . = ALIGN(4096); - .reloc : + .rodata ALIGN(4096) : ALIGN(4096) { - *(.reloc) - } + _rodata = .; + *(.rodata*) + *(.srodata*) - . = ALIGN(4096); - .hash : ALIGN(1) { *(.hash) } - .gnu.hash : ALIGN(1) { *(.gnu.hash) } - .dynsym : ALIGN(4096) { *(.dynsym) } - .dynstr : ALIGN(4096) { *(.dynstr) } - .eh_frame_hdr : ALIGN(1) { *(.eh_frame_hdr) } - .eh_frame : ALIGN(1) { *(.eh_frame) } + /* + * Note that these aren't the using the GNU "CONSTRUCTOR" output section + * command, so they don't start with a size. Because of p2align and the + * end/END definitions, and the fact that they're mergeable, they can also + * have NULLs which aren't guaranteed to be at the end. + */ + . = ALIGN(16); + _init_array = .; + *(SORT_BY_INIT_PRIORITY(.init_array*)) + FILL(0x0); + . = ALIGN(16); + _init_array_end = .; + __CTOR_LIST__ = .; + *(SORT_BY_NAME(.ctors)) + FILL(0x0); + . = ALIGN(16); + __CTOR_END__ = .; + __DTOR_LIST__ = .; + *(SORT_BY_NAME(.dtors)) + FILL(0x0); + . = ALIGN(16); + __DTOR_END__ = .; + _fini_array = .; + *(SORT_BY_INIT_PRIORITY(.fini_array*)) + FILL(0x0); + . = ALIGN(16); + _fini_array_end = .; + + . = ALIGN(4096); + _erodata = .; + _rodata_size = _erodata - _rodata; + } :load + + .data.rel ALIGN(512) : ALIGN(512) + { + _data_rel = .; + *(.data.rel) + . = ALIGN(512); + _edata_rel = .; + _data_rel_size = _edata_rel - _data_rel; + } :load + + .data.rel.local ALIGN(512) : ALIGN(512) + { + _data_rel_local = .; + *(.data.rel.local) + . = ALIGN(512); + _edata_rel_local = .; + _data_rel_local_size = _edata_rel_local - _data_rel_local; + } :load + + .data.rel.ro ALIGN(512) : ALIGN(512) + { + _data_rel_ro = .; + *(.data.rel.ro) + . = ALIGN(512); + _edata_rel_ro = .; + _data_rel_ro_size = _edata_rel_ro - _data_rel_ro; + } :load + + .data.rel.ro.local ALIGN(512) : ALIGN(512) + { + _data_rel_ro_local = .; + *(.data.rel.ro.local) + . = ALIGN(512); + _edata_rel_ro_local = .; + _data_rel_ro_local_size = _edata_rel_ro_local - _data_rel_ro_local; + } :load + + .data.ident ALIGN(512) : ALIGN(512) + { + _data_ident = .; + *(.data.ident) + . = ALIGN(512); + _edata_ident = .; + _data_ident_size = _edata_ident - _data_ident; + } :load =0xa5a5a5a5 + + .eh_frame_hdr ALIGN(512) : ALIGN(512) + { + _eh_frame_hdr = .; + *(.eh_frame_hdr) + . = ALIGN(512); + _eeh_frame_hdr = .; + _eh_frame_hdr_size = _eeh_frame_hdr - _eh_frame_hdr; + } :load + + .eh_frame ALIGN(512) : ALIGN(512) + { + _eh_frame = .; + *(.eh_frame) + . = ALIGN(512); + _eeh_frame = .; + _eh_frame_size = _eeh_frame - _eh_frame; + } :load + + .dynamic ALIGN(4096) : ALIGN(4096) + { + _dynamic = .; + *(.dynamic) + . = ALIGN(4096); + _edynamic = .; + _dynamic_size = _edynamic - _dynamic; + } :load + + .hash : + { + *(.hash) + } :load + + .gnu.hash : + { + *(.gnu.hash) + } :load + + .dynstr ALIGN(4096) : ALIGN(4096) + { + _dynstr = .; + *(.dynstr) + . = ALIGN(4096); + _edynstr = .; + _dynstr_size = _edynstr - _dynstr; + } :load + + .dynsym ALIGN(4096) : ALIGN(4096) + { + _dynsym = .; + *(.dynsym) + . = ALIGN(4096); + _edynsym = .; + _dynsym_size = _edynsym - _dynsym; + } :load + + .rela ALIGN(4096) : ALIGN(4096) + { + _rela = .; + *(.rela) + *(.rela.*) + _erela = .; + _rela_size = _erela - _rela; + } :load + + .rel ALIGN(4096) : ALIGN(4096) + { + _rel = .; + *(.rel) + *(.rel.*) + _erel = .; + _rel_size = _erel - _rel; + } :load + + .note.gnu.build-id ALIGN(512) : ALIGN(512) + { + _note_gnu_build_id = .; + *(.note.gnu.build-id) + . = ALIGN(512); + _enote_gnu_build_id = .; + _note_gnu_build_id_size = _enote_gnu_build_id - _note_gnu_build_id; + } :load /* DWARF debug sections. Symbols in the DWARF debugging sections are relative to the beginning of the section so we begin them at 0. */ /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } + /* .debug ALIGN(4096) (NOLOAD) : ALIGN(4096) { *(.debug) } :NONE */ + /* .line (NOLOAD) : { *(.line) } :NONE */ /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } + /* .debug_aranges (NOLOAD) : { *(.debug_aranges) } :NONE */ + /* .debug_srcinfo (NOLOAD) : { *(.debug_srcinfo) } :NONE */ + /* .debug_sfnames (NOLOAD) : { *(.debug_sfnames) } :NONE */ + /* .debug_pubnames (NOLOAD) : { *(.debug_pubnames) } :NONE */ + /* DWARF 2 */ - .debug_info 0 : { *(.debug_info) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - .debug_macro 0 : { *(.debug_macro*) } - .debug_ranges 0 : { *(.debug_ranges) } + .debug_info (NOLOAD) : { *(.debug_info) } :NONE + .debug_abbrev (NOLOAD) : { *(.debug_abbrev) } :NONE + .debug_aranges (NOLOAD) : { *(.debug_aranges) } :NONE + .debug_ranges (NOLOAD) : { *(.debug_ranges) } :NONE + .debug_line (NOLOAD) : { *(.debug_line) } :NONE + .debug_str (NOLOAD) : { *(.debug_str) } :NONE + + .debug_frame (NOLOAD) : { *(.debug_frame) } :NONE + .debug_loc (NOLOAD) : { *(.debug_loc) } :NONE + .debug_macinfo (NOLOAD) : { *(.debug_macinfo) } :NONE + .debug_macro (NOLOAD) : { *(.debug_macro*) } :NONE + /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } + .debug_weaknames (NOLOAD) : { *(.debug_weaknames) } :NONE + .debug_funcnames (NOLOAD) : { *(.debug_funcnames) } :NONE + .debug_typenames (NOLOAD) : { *(.debug_typenames) } :NONE + .debug_varnames (NOLOAD) : { *(.debug_varnames) } :NONE /DISCARD/ : { @@ -154,6 +273,6 @@ SECTIONS *(.gnu.version_d) *(.gnu.version_r) *(.gnu.version) + *(.comment) } - .comment 0 : { *(.comment) } } diff --git a/gnuefi/reloc_x64.c b/gnuefi/reloc_x64.c index d5467db..43cfba4 100644 --- a/gnuefi/reloc_x64.c +++ b/gnuefi/reloc_x64.c @@ -68,10 +68,51 @@ printval_(EFI_SYSTEM_TABLE *systab, int size, uint64_t value) case 8: default: shift = 60; - if (!(value & 0xffffffff00000000ull)) - shift >>= 1; break; } + + // value = 0x00000070 + // shift = 12 + // i = 16 + // mask = ~((1<<16)-1) = ~(0x10000-1) = ~0xffff = 0xffff0000 + // mask & value = 0x00000000 + // i = 12 + // mask = ~((1<<12)-1) = ~(0x1000-1) = ~0xfff = 0xfffff000 + // mask & value = 0x00000000 + // i = 8 + // mask = ~((1<<8)-1) = ~(0x100-1) = ~0xff = 0xffffff00 + // mask & value = 0x00000000 + // i = 4 + // mask = ~((1<<4)-1) = ~(0x10-1) = ~0xf = 0xfffffff0 + // mask & value = 0x000000b0 + // i = 8 + // break + + for (i = shift + 4; i > 4; i -= 4) { + mask = ~((1 << i) - 1); + if (value & mask) { + i += 4; + break; + } + } + shift = i; +#if 0 + if (!(value & 0xffffffffffffff00ull) && shift > 4) + shift = 4; + else if (!(value & 0xffffffffffff0000ull) && shift > 12) + shift = 12; + else if (!(value & 0xffffffffff000000ull) && shift > 20) + shift = 20; + else if (!(value & 0xffffffff00000000ull) && shift > 28) + shift = 28; + else if (!(value & 0xffffff0000000000ull) && shift > 36) + shift = 36; + else if (!(value & 0xffff000000000000ull) && shift > 44) + shift = 44; + else if (!(value & 0xff00000000000000ull) && shift > 52) + shift = 52; +#endif + mask = 0xfull << shift; for (i = 2; mask != 0; i += 2) { @@ -94,92 +135,321 @@ print_(EFI_SYSTEM_TABLE *systab, wchar_t *str) systab->ConOut->OutputString(systab->ConOut, str); } +#if 0 +#define _STRING(x) #x +#define STRING(x) _STRING(x) +#define CONCAT(x,y) x ## y + +#define STARTSTOP(x,y) \ + ".weakref _" STRING(x) ", _start_." STRING(y) "\n" \ + ".weakref _e" STRING(x) ", _stop_." STRING(y) "\n" +__asm__ ( +STARTSTOP(text, text) +STARTSTOP(reloc, reloc) +STARTSTOP(data, data) +STARTSTOP(bss, bss) +STARTSTOP(rodata, rodata) +STARTSTOP(data_rel, data.rel) +STARTSTOP(data_rel_local, data.rel.local) +STARTSTOP(data_rel_ro, data.rel.ro) +STARTSTOP(data_rel_ro_local, data.rel.ro.local) +STARTSTOP(data_rela, data.rela) +STARTSTOP(data_rela_local, data.rela.local) +STARTSTOP(data_rela_ro, data.rela.ro) +STARTSTOP(data_rela_ro_local, data.rela.ro.local) +STARTSTOP(dynsym, dynsym) +STARTSTOP(dynstr, dynstr) +STARTSTOP(rel, rel) +STARTSTOP(rela, rela) +STARTSTOP(dynamic, dynamic) +STARTSTOP(eh_frame_hdr, eh_frame_hdr) +STARTSTOP(eh_frame, eh_frame) +); +#endif + + +extern uint8_t + _text, _etext, + _reloc, _ereloc, + _data, _edata, + _bss, _ebss, + _rodata, _erodata, +#if 0 + _data_rel, _edata_rel, + _data_rel_local, _edata_rel_local, + _data_rel_ro, _edata_rel_ro, + _data_rel_ro_local, _edata_rel_ro_local, +#endif + _dynsym, _edynsym, + _dynstr, _edynstr, +#if 0 + _data_ident, _edata_ident, + _rel, _erel, + _rela, _erela, +#endif + _dynamic, _edynamic, + _note_gnu_build_id, _enote_gnu_build_id, + _eh_frame_hdr, _eeh_frame_hdr, + _eh_frame, _eeh_frame + ; + +static struct { + void *begin; + void *end; + wchar_t name[32]; +} _sections[] = { + { &_text, &_etext, L".text" }, + { &_reloc, &_ereloc, L".relocl" }, + { &_data, &_edata, L".data" }, + { &_bss, &_ebss, L".bss" }, + { &_rodata, &_erodata, L".rodata" }, +#if 0 + { &_data_rel, &_edata_rel, L".data.rel" }, + { &_data_rel_local, &_edata_rel_local, L".data.rel.local" }, + { &_data_rel_ro, &_edata_rel_ro, L".data.rel.ro" }, + { &_data_rel_ro_local, &_edata_rel_ro_local, L".data.rel.ro.local" }, +#endif + { &_dynsym, &_edynsym, L".dynsym" }, + { &_dynstr, &_edynstr, L".dynstr" }, +#if 0 + { &_data_ident, &_edata_ident, L".data.ident" }, + { &_rel, &_erel, L".rel" }, + { &_rela, &_erela, L".rela" }, +#endif + { &_dynamic, &_edynamic, L".dynamic" }, + { &_note_gnu_build_id, &_enote_gnu_build_id, L".note.gnu.build-id" }, + { &_eh_frame_hdr, &_eeh_frame_hdr, L".eh_frame_hdr" }, + { &_eh_frame, &_eeh_frame, L".eh_frame" }, + { NULL, NULL, L"" } +}; + +static void +__attribute__((__unused__)) +printsection_(EFI_SYSTEM_TABLE *systab, uint64_t addr) +{ + unsigned int i; + void *obj = (void *)addr; + for (i = 0; _sections[i].name[0] != L'\0'; i++) { + if (_sections[i].begin >= obj && _sections[i].end <= obj) { + print_(systab, _sections[i].name); + return; + } + } + print_(systab, L"unknown section"); +} + #ifdef EFI_DEBUG #define printval(a) printval_(systab, sizeof(a), (uint64_t)(a)) #define print(x) print_(systab, (x)) +#define printsection(obj) printsection_(systab, obj) #else #define printval(a) #define print(x) +#define printsection(obj) #endif -extern uint8_t _bstart, _bend; +extern uint8_t ImageBase; -EFI_STATUS _relocate (unsigned long ldbase, Elf64_Dyn *dyn, - EFI_HANDLE image EFI_UNUSED, - EFI_SYSTEM_TABLE *systab EFI_UNUSED) +EFI_STATUS EFIAPI _relocate (unsigned long ldbase, Elf64_Dyn *dyn, + EFI_HANDLE image EFI_UNUSED, + EFI_SYSTEM_TABLE *systab EFI_UNUSED) { - long relsz = 0, relent = 0; + Elf64_Rela *rela = 0; + uint64_t relasz = 0, relaent = 0; + uint64_t relsz = 0, relent = 0; Elf64_Rel *rel = 0; unsigned long *addr = NULL; int i; - print(L"ldbase:"); printval(ldbase); - print(L" dyn:"); printval(dyn); print(L"\r\n"); + print(L" ldbase:"); printval(ldbase); + print(L" dyn:"); printval(dyn); + print(L" img:"); printval(image); + print(L" systab:"); printval(systab); + print(L"\r\n"); for (i = 0; dyn[i].d_tag != DT_NULL; ++i) { print(L"i:"); printval(i); print(L" tag:"); printval(dyn[i].d_tag); print(L" "); switch (dyn[i].d_tag) { - case DT_NULL: print(L"DT_NULL"); break; - case DT_NEEDED: print(L"DT_NEEDED:\t"); printval(dyn[i].d_un.d_val); break; - case DT_PLTRELSZ: print(L"DT_PLTRELSZ:\t"); printval(dyn[i].d_un.d_val); break; - case DT_PLTGOT: print(L"DT_PLTGOT:\t"); printval(dyn[i].d_un.d_ptr); break; - case DT_HASH: print(L"DT_HASH:\t"); printval(dyn[i].d_un.d_ptr); break; - case DT_STRTAB: print(L"DT_STRTAB:\t"); printval(dyn[i].d_un.d_ptr); break; - case DT_SYMTAB: print(L"DT_SYMTAB:\t"); printval(dyn[i].d_un.d_ptr); break; - + case DT_NULL: + print(L"DT_NULL"); + break; + case DT_NEEDED: + print(L"DT_NEEDED: "); + printval(dyn[i].d_un.d_val); + break; + case DT_PLTRELSZ: + print(L"DT_PLTRELSZ: "); + printval(dyn[i].d_un.d_val); + break; + case DT_PLTGOT: + print(L"DT_PLTGOT: "); + printval(dyn[i].d_un.d_ptr); + break; + case DT_HASH: + print(L"DT_HASH: "); + printval(dyn[i].d_un.d_ptr); + break; + case DT_STRTAB: + print(L"DT_STRTAB: "); + printval(dyn[i].d_un.d_ptr); + break; + case DT_SYMTAB: + print(L"DT_SYMTAB: "); + printval(dyn[i].d_un.d_ptr); + break; case DT_RELA: + rela = (Elf64_Rela*) + ((unsigned long)dyn[i].d_un.d_ptr + + ldbase); + print(L"DT_RELA: "); + printval((unsigned long)dyn[i].d_un.d_ptr); + print(L"+ldbase->"); + printval(rela); + break; + case DT_RELASZ: + relasz = dyn[i].d_un.d_val; + print(L"DT_RELASZ: "); + printval(relasz); + break; + case DT_RELAENT: + relaent = dyn[i].d_un.d_val; + print(L"DT_RELAENT: "); + printval(relaent); + break; + case DT_STRSZ: + print(L"DT_STRSZ: "); + printval(dyn[i].d_un.d_val); + break; + case DT_SYMENT: + print(L"DT_SYMENT: "); + printval(dyn[i].d_un.d_val); + break; + case DT_INIT: + print(L"DT_INIT: "); + printval(dyn[i].d_un.d_ptr); + break; + case DT_FINI: + print(L"DT_FINI: "); + printval(dyn[i].d_un.d_ptr); + break; + case DT_SONAME: + print(L"DT_SONAME: "); + printval(dyn[i].d_un.d_val); + break; + case DT_RPATH: + print(L"DT_RPATH: "); + printval(dyn[i].d_un.d_val); + break; + case DT_SYMBOLIC: + print(L"DT_SYMBOLIC"); + break; + case DT_REL: rel = (Elf64_Rel*) ((unsigned long)dyn[i].d_un.d_ptr + ldbase); - print(L"DT_RELA:\t"); printval(rel); + print(L"DT_REL: "); + printval((unsigned long)dyn[i].d_un.d_ptr); + print(L"+ldbase->"); + printval(rel); break; - - case DT_RELASZ: + case DT_RELSZ: relsz = dyn[i].d_un.d_val; - print(L"DT_RELASZ:\t"); printval(relsz); + print(L"DT_RELSZ: "); + printval(relsz); break; - - case DT_RELAENT: + case DT_RELENT: relent = dyn[i].d_un.d_val; - print(L"DT_RELAENT:\t"); printval(relent); + print(L"DT_RELENT: "); + printval(relent); + break; + case DT_PLTREL: + print(L"DT_PLTREL: "); + printval(dyn[i].d_un.d_val); + break; + case DT_DEBUG: + print(L"DT_DEBUG: "); + printval(dyn[i].d_un.d_ptr); + break; + case DT_TEXTREL: + print(L"DT_TEXTREL"); + break; + case DT_JMPREL: + print(L"DT_JMPREL: "); + printval(dyn[i].d_un.d_ptr); + break; + case DT_BIND_NOW: + print(L"DT_BIND_NOW"); + break; + case DT_LOPROC: + print(L"DT_LOPROC: "); + printval((uint32_t)0x70000000u); + break; + case DT_HIPROC: + print(L"DT_HIPROC: "); + printval((uint32_t)0x7fffffffu); break; - case DT_STRSZ: print(L"DT_STRSZ:\t"); printval(dyn[i].d_un.d_val); break; - case DT_SYMENT: print(L"DT_SYMENT:\t"); printval(dyn[i].d_un.d_val); break; - case DT_INIT: print(L"DT_INIT:\t"); printval(dyn[i].d_un.d_ptr); break; - case DT_FINI: print(L"DT_FINI:\t"); printval(dyn[i].d_un.d_ptr); break; - case DT_SONAME: print(L"DT_SONAME:\t"); printval(dyn[i].d_un.d_val); break; - case DT_RPATH: print(L"DT_RPATH:\t"); printval(dyn[i].d_un.d_val); break; - case DT_SYMBOLIC: print(L"DT_SYMBOLIC"); break; - case DT_REL: print(L"DT_REL:\t"); printval(dyn[i].d_un.d_ptr); break; - case DT_RELSZ: print(L"DT_RELSZ:\t"); printval(dyn[i].d_un.d_val); break; - case DT_RELENT: print(L"DT_RELENT:\t"); printval(dyn[i].d_un.d_val); break; - case DT_PLTREL: print(L"DT_PLTREL:\t"); printval(dyn[i].d_un.d_val); break; - case DT_DEBUG: print(L"DT_DEBUG:\t"); printval(dyn[i].d_un.d_ptr); break; - case DT_TEXTREL: print(L"DT_TEXTREL"); break; - case DT_JMPREL: print(L"DT_JMPREL:\t"); printval(dyn[i].d_un.d_ptr); break; - case DT_BIND_NOW: print(L"DT_BIND_NOW"); break; - case DT_LOPROC: print(L"DT_LOPROC:\t"); printval((uint32_t)0x70000000u); break; - case DT_HIPROC: print(L"DT_HIPROC:\t"); printval((uint32_t)0x7fffffffu); break; - default: - print(L"UNKNOWN:\t"); + print(L"UNKNOWN: "); printval(dyn[i].d_un.d_val); break; } print(L"\r\n"); } - if (!rel && relent == 0) { - print(L"!rel && relent == 0\r\n"); - return EFI_SUCCESS; + if (!rel && !rela && relent == 0 && relaent == 0) { + print(L"!rela && relaent == 0 && !rel && relent == 0\r\n"); + return EFI_SUCCESS; } - if (!rel || relent == 0) { - print(L"!rel || relent == 0\r\n"); + if ((!rel || relent == 0) && (!rela || relaent == 0)) { + if (!rela && relaent == 0) + print(L"!rela || relaent == 0\r\n"); + if (!rel && relent == 0) + print(L"!rel || relent == 0\r\n"); return EFI_LOAD_ERROR; } + while (relasz > 0) { + /* apply the relocs */ + switch (ELF64_R_TYPE (rela->r_info)) { + case R_X86_64_NONE: + addr = (unsigned long *) + (ldbase + rela->r_offset); + print(L"NONE"); + print(L" offset:"); printval(rela->r_offset); + print(L" *rela:"); printval(*addr); + print(L" +addend:"); printval(rela->r_addend); + print(L" "); printsection(*addr); + break; + + case R_X86_64_RELATIVE: + addr = (unsigned long *) + (ldbase + rela->r_offset); + print(L"RELA"); + print(L" offset:"); printval(rela->r_offset); + print(L" *rela:"); printval(*addr); + print(L" +addend:"); printval(rela->r_addend); + print(L"->"); + *addr += ldbase; + *addr += rela->r_addend; + printval(*addr); + print(L" "); printsection(*addr - ldbase); + break; + + default: + print(L"???? tag:"); + printval(dyn[i].d_tag); + print(L" offset:"); + printval(rela->r_offset); + print(L" "); printsection(rela->r_offset); + break; + } + print(L"\r\n"); + rela = (Elf64_Rela*) ((char *) rela + relaent); + relasz -= relaent; + } + while (relsz > 0) { /* apply the relocs */ switch (ELF64_R_TYPE (rel->r_info)) { @@ -189,17 +459,19 @@ EFI_STATUS _relocate (unsigned long ldbase, Elf64_Dyn *dyn, print(L"NONE"); print(L" offset:"); printval(rel->r_offset); print(L" *rel:"); printval(*addr); + print(L" "); printsection(*addr); break; case R_X86_64_RELATIVE: addr = (unsigned long *) (ldbase + rel->r_offset); - print(L"RELA"); + print(L"REL"); print(L" offset:"); printval(rel->r_offset); print(L" *rel:"); printval(*addr); print(L"->"); *addr += ldbase; printval(*addr); + print(L" "); printsection(*addr - ldbase); break; default: @@ -207,6 +479,7 @@ EFI_STATUS _relocate (unsigned long ldbase, Elf64_Dyn *dyn, printval(dyn[i].d_tag); print(L" offset:"); printval(rel->r_offset); + print(L" "); printsection(rel->r_offset); break; } print(L"\r\n"); @@ -214,11 +487,11 @@ EFI_STATUS _relocate (unsigned long ldbase, Elf64_Dyn *dyn, relsz -= relent; } print(L"zeroing "); - printval(&_bstart - &_bend); + printval(&_ebss - &_bss); print(L" bytes of .bss at "); - printval(&_bstart); + printval(&_bss); print(L"\r\n"); - ZeroMem(&_bstart, &_bend - &_bstart); + ZeroMem(&_bss, &_ebss - &_bss); print(L"returning success\r\n"); return EFI_SUCCESS; diff --git a/inc/efi.mk.in b/inc/efi.mk.in index e88a127..14f11f0 100644 --- a/inc/efi.mk.in +++ b/inc/efi.mk.in @@ -75,10 +75,11 @@ _EFI_CCLDLIBS = $(subst $(_efi_space),$(_efi_comma),-Wl --start-group $(foreach EFI_BIN_SECTIONS ?= .text .sdata .data .dynamic .dynsym \ .rel .rel.* .rela .rela.* .reloc \ - .eh_frame .note.gnu.build-id .ctf \ + .eh_frame* .note.gnu.build-id .ctf \ + .debug* \ $(EFI_ARCH_BIN_SECTIONS) -EFI_DEBUG_SECTIONS ?= .debug* .eh_frame .note.gnu.build-id .ctf \ +EFI_DEBUG_SECTIONS ?= .debug* .eh_frame* .note.gnu.build-id .ctf \ $(EFI_ARCH_DEBUG_SECTIONS) EFI_OBJCOPY_FLAGS ?= --file-alignment 512 --section-alignment 4096 -D @@ -87,7 +88,7 @@ ifneq ($(EFI_OBJCOPY_GTE224),1) $(error objcopy >= 2.24 is required) endif $(OBJCOPY) $(EFI_OBJCOPY_FLAGS) \ - $(foreach x,$(EFI_BIN_SECTIONS),-j $(x)) \ + $(foreach x,$(EFI_BIN_SECTIONS),-j "$(x))" \ $(EFI_ARCH_FORMAT) $*.efi.so $@ %.efi.debug : %.efi.so @@ -95,7 +96,7 @@ ifneq ($(EFI_OBJCOPY_GTE224),1) $(error objcopy >= 2.24 is required) endif $(OBJCOPY) $(EFI_OBJCOPY_FLAGS) \ - $(foreach x,$(EFI_DEBUG_SECTIONS),-j $(x)) \ + $(foreach x,$(EFI_DEBUG_SECTIONS),-j "$(x)") \ $(EFI_ARCH_FORMAT) $*.efi.so $@ %.efi.a : diff --git a/lib/dpath.c b/lib/dpath.c index 72b2750..aeb30e8 100644 --- a/lib/dpath.c +++ b/lib/dpath.c @@ -981,7 +981,7 @@ _DevPathFilePath ( Print(L"%a:%d Fp:%xh\n", __FILE__, __LINE__, Fp); Print(L"%a:%d Fp->PathName:%xh\n", __FILE__, __LINE__, Fp->PathName); CatPrint(Str, L"%s", Fp->PathName); - Print(L"%a:%d\n", __FILE__, __LINE__); + Print(L"%a:%d Str:\"%s\"\n", __FILE__, __LINE__, Str); } static VOID @@ -1140,16 +1140,13 @@ DevicePathToStr ( VOID (*DumpNode)(POOL_PRINT *, VOID *); UINTN Index, NewSize; - Print(L"%a:%d\n", __FILE__, __LINE__); ZeroMem(&Str, sizeof(Str)); // // Unpacked the device path // - Print(L"%a:%d\n", __FILE__, __LINE__); DevPath = UnpackDevicePath(DevPath); - Print(L"%a:%d\n", __FILE__, __LINE__); ASSERT (DevPath); @@ -1158,21 +1155,17 @@ DevicePathToStr ( // DevPathNode = DevPath; - Print(L"%a:%d\n", __FILE__, __LINE__); while (!IsDevicePathEnd(DevPathNode)) { - Print(L"%a:%d\n", __FILE__, __LINE__); // // Find the handler to dump this device path node // DumpNode = NULL; for (Index = 0; DevPathTable[Index].Function; Index += 1) { - Print(L"%a:%d\n", __FILE__, __LINE__); if (DevicePathType(DevPathNode) == DevPathTable[Index].Type && DevicePathSubType(DevPathNode) == DevPathTable[Index].SubType) { DumpNode = DevPathTable[Index].Function; - Print(L"%a:%d,idx=%d DumpNode:%xh\n", __FILE__, __LINE__, Index, DumpNode); break; } } @@ -1182,7 +1175,6 @@ DevicePathToStr ( // if (!DumpNode) { - Print(L"%a:%d\n", __FILE__, __LINE__); DumpNode = _DevPathNodeUnknown; } @@ -1191,7 +1183,6 @@ DevicePathToStr ( // if (Str.len && DumpNode != _DevPathEndInstance) { - Print(L"%a:%d\n", __FILE__, __LINE__); CatPrint (&Str, L"/"); } @@ -1199,31 +1190,23 @@ DevicePathToStr ( // Print this node of the device path // - Print(L"%a:%d\n", __FILE__, __LINE__); DumpNode (&Str, DevPathNode); // // Next device path node // - Print(L"%a:%d\n", __FILE__, __LINE__); DevPathNode = NextDevicePathNode(DevPathNode); - Print(L"%a:%d\n", __FILE__, __LINE__); } // // Shrink pool used for string allocation // - Print(L"%a:%d\n", __FILE__, __LINE__); FreePool (DevPath); - Print(L"%a:%d\n", __FILE__, __LINE__); NewSize = (Str.len + 1) * sizeof(CHAR16); - Print(L"%a:%d\n", __FILE__, __LINE__); Str.str = ReallocatePool (Str.str, NewSize, NewSize); - Print(L"%a:%d\n", __FILE__, __LINE__); Str.str[Str.len] = 0; - Print(L"%a:%d\n", __FILE__, __LINE__); return Str.str; }