Hi ROM, When I am trying to use libpayload in my own usbrom, i find that I the function point seems wrong. In my main.c files: int main(int argc, char **argv){
const char *s="foo"; console_init();
puts(s);//the address of s which should passed to puts was wrong //// I check it with HDT find it move address 262c to[esp].
while(1); return 0; } I really do not know why, and my ldscript is
OUTPUT_FORMAT("elf32-i386") OUTPUT_ARCH(i386) ENTRY(_setup) /* 32KB heap and 16KB stack */ HEAP_SIZE = 32768; STACK_SIZE = 16384;
__boot_vect = 0x0000;
SECTIONS {
.text __boot_vect : { *( .text) } = 0x00
.rodata ALIGN(4) : { *( .rodata) } = 0x00
.data ALIGN(4) : { *( .data) } = 0x00
.bss ALIGN(4) : { *( .bss) /* heap and stack */
. = ALIGN(16); _heap = .; . += HEAP_SIZE; . = ALIGN(16); _eheap = .;
_stack = .; . += STACK_SIZE; . = ALIGN(16); _estack = .; } = 0x00
} and Makefile is export obj := $(shell pwd)/build export src := $(shell pwd)/src export build := $(shell pwd)/build
ifeq ($(V),1) Q := @ endif
TARGETS-y := head.o main.o OBJS := $(patsubst %,$(obj)/%,$(TARGETS-y))
ROM_OBJ= $(obj)/usb.rom ROM_BIN= $(obj)/usb.bin ROM_SIZE= 65536
OBJCOPY= objcopy OBJCOPY_FLAGS= -O binary BUILD_ROM= ./build_rom
LIBPAYLOAD_PREFIX= /opt/libpayload LIBPAYLOAD=$(LIBPAYLOAD_PREFIX)/lib/libpayload.a INCPAYLOAD=$(LIBPAYLOAD_PREFIX)/include/
STACKPROTECT += $(call cc-option, -fno-stack-protector,) GCCINCDIR = $(shell $(CC) -print-search-dirs | head -n 1 | cut -d' ' -f2)include/
INCLUDES := -I$(INCPAYLOAD) -Iinclude -Ibuild INCLUDES += -Iinclude -Ibuild INCLUDES += -I$(GCCINCDIR) -I$(INCPAYLOAD)/i386/
CFLAGS += -Wall $(STACKPROTECT) $(INCLUDES) -c -fno-builtin -nostdinc -Werror -Os -fomit-frame-pointer -fno-common -ffreestanding -fno-strict-aliasing CFLAGS= $(STACKPROTECT) $(INCLUDES) -c -fno-builtin -nostdinc -O2 -I. -Wall -Werror
LIBGCC = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
all:$(ROM_BIN)
$(ROM_BIN): $(OBJS) $(Q)printf " LD $(subst $(shell pwd)/,,$(@))\n" $(Q)$(LD) -T $(src)/ldscript -static -o $@ $(OBJS) $(LIBPAYLOAD) $(LIBGCC) $(Q)$(OBJCOPY) $(OBJCOPY_FLAGS) $(ROM_BIN) $(ROM_OBJ) $(Q)$(BUILD_ROM) $(ROM_OBJ) $(ROM_SIZE)
$(obj)/%.o: $(src)/%.c $(Q)printf " CC $(subst $(shell pwd)/,,$(@))\n" $(Q)$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
$(obj)/%.o: $(src)/%.S $(Q)printf " AS $(subst $(shell pwd)/,,$(@))\n" $(Q)$(AS) -o $@ $<
prepare: $(Q)printf " SH building/preparing libpayload\n" $(Q)./prepare.sh
clean: $(Q)printf " SH cleaning $(obj)\n" $(Q)rm -f $(obj)/*.o $(obj)/*.rom $(obj)/*.bin
distclean: clean $(Q)printf " SH cleaning $(src)\n" @rm -Rf build @rm -Rf libpayload i also attached all of my source file. Could you please help me to take a look at this? Thanks.
I will try to look at this later today. I am in the middle of preparing a talk for ISC 2009 and am kind of overloaded :-)
I will do my best.
ron
Hi Jason,
Just got this built. I have added -m32 to the cflags and --32 to AS flags to get it building on 64bit. You might want to add that.
Just to reiterate the problem. I objdump the usb.bin and I see that the offset to the string is not relative but absolute.
Here is main 00000110 <main>: 110: 8d 4c 24 04 lea 0x4(%esp),%ecx 114: 83 e4 f0 and $0xfffffff0,%esp 117: ff 71 fc pushl -0x4(%ecx) 11a: 55 push %ebp 11b: 89 e5 mov %esp,%ebp 11d: 51 push %ecx 11e: 83 ec 04 sub $0x4,%esp 121: e8 3c 00 00 00 call 162 <console_init> 126: c7 04 24 45 42 00 00 movl $0x4245,(%esp) <------ that is the problem line. 12d: e8 ae 00 00 00 call 1e0 <puts> 132: eb fe jmp 132 <main+0x22>
and data; 66, 6f, 6f is 'foo' 00004245 <.rodata.str1.1>: 4245: 66 6f outsw %ds:(%esi),(%dx) 4247: 6f outsl %ds:(%esi),(%dx)
I don't know enough about how this is supposed to work but it looks like the linker is setting the base to 0x00
.rodata ALIGN(4) : { *( .rodata) } = 0x00
and that is exactly what is in the address, 45 42 00 00.
So, I added -fPIC to the CFLAGS and the code changes to this:
132: 8d 83 cd fa ff ff lea -0x533(%ebx),%eax 138: 89 04 24 mov %eax,(%esp) 13b: e8 b0 00 00 00 call 1f0 <puts>
which seems better since it is building a relative offset but I have no idea if it is correct.
It seems like there are a few things that need understanding. 1. How to make the code relocatable. 2. Is libpayload being built so that it can be used relocatable.
Marc
-fpic is the wrong way to go ... can we talk about this relocatable code a bit? I need to catch up.
For any assembly code, if it needs to be 32-bit, it's always a good idea to have .code32 at the start
thanks
ron
On Wed, Jun 17, 2009 at 11:05 AM, ron minnichrminnich@gmail.com wrote:
-fpic is the wrong way to go ... can we talk about this relocatable code a bit? I need to catch up.
The code is a PCI option ROM that can be copied and run at some arbitrary location between 0xC0000 and 0x100000. For 16bit code the segment would be loaded and there is no problem. I don't know the right way to do this for 32bit flat mode code.
Marc
On Wed, Jun 17, 2009 at 10:15 AM, Marc Jonesmarcj303@gmail.com wrote:
On Wed, Jun 17, 2009 at 11:05 AM, ron minnichrminnich@gmail.com wrote:
-fpic is the wrong way to go ... can we talk about this relocatable code a bit? I need to catch up.
The code is a PCI option ROM that can be copied and run at some arbitrary location between 0xC0000 and 0x100000. For 16bit code the segment would be loaded and there is no problem. I don't know the right way to do this for 32bit flat mode code.
I think we need to seek a common solution, and after discussion with segher from a while back I think -fpic and -fpie as we do it in v3 are rather questionable.
What we should look to do is a run command which sets a new entry in the gdt and does a ljmp which sets CS to that entry. Then we link with that code to run at 0. This is what FILO does and it works well.
thanks
ron
On Wed, Jun 17, 2009 at 11:18 AM, ron minnichrminnich@gmail.com wrote:
On Wed, Jun 17, 2009 at 10:15 AM, Marc Jonesmarcj303@gmail.com wrote:
On Wed, Jun 17, 2009 at 11:05 AM, ron minnichrminnich@gmail.com wrote:
-fpic is the wrong way to go ... can we talk about this relocatable code a bit? I need to catch up.
The code is a PCI option ROM that can be copied and run at some arbitrary location between 0xC0000 and 0x100000. For 16bit code the segment would be loaded and there is no problem. I don't know the right way to do this for 32bit flat mode code.
I think we need to seek a common solution, and after discussion with segher from a while back I think -fpic and -fpie as we do it in v3 are rather questionable.
What we should look to do is a run command which sets a new entry in the gdt and does a ljmp which sets CS to that entry. Then we link with that code to run at 0. This is what FILO does and it works well.
Ron, That is a much better solution.
Jason, Let me know if you need help with that.
We should probably make a wiki article about it since it seems to come up now and then.
Marc
Hey Ron,
I'll write later about this, but please don't rule out PIC just because Segher warned you.
On 17.06.2009 19:18, ron minnich wrote:
I think we need to seek a common solution, and after discussion with segher from a while back I think -fpic and -fpie as we do it in v3 are rather questionable.
Regards, Carl-Daniel
Hi all, I have already succeed in using libpayload after set up the right GDT. I forget to set the right base addres for the data after setting up the coding address. It works now, thanks all
On Thu, Jun 18, 2009 at 1:44 AM, Carl-Daniel Hailfinger < c-d.hailfinger.devel.2006@gmx.net> wrote:
Hey Ron,
I'll write later about this, but please don't rule out PIC just because Segher warned you.
On 17.06.2009 19:18, ron minnich wrote:
I think we need to seek a common solution, and after discussion with segher from a while back I think -fpic and -fpie as we do it in v3 are rather questionable.
Regards, Carl-Daniel
On 17.06.2009 19:18, ron minnich wrote:
On Wed, Jun 17, 2009 at 10:15 AM, Marc Jonesmarcj303@gmail.com wrote:
The code is a PCI option ROM that can be copied and run at some arbitrary location between 0xC0000 and 0x100000. For 16bit code the segment would be loaded and there is no problem. I don't know the right way to do this for 32bit flat mode code.
I think we need to seek a common solution, and after discussion with segher from a while back I think -fpic and -fpie as we do it in v3 are rather questionable.
-fpic/-fpie may not be an universally preferred solution, but if GCC developers ever decide to drop support for it, we can still move to LLVM/clang. v3 initram is a bit of a special case because it is PIC calling non-PIC. As far as I can see, GDT trickery would not work for such a case.
What we should look to do is a run command which sets a new entry in the gdt and does a ljmp which sets CS to that entry. Then we link with that code to run at 0. This is what FILO does and it works well.
As long as the code does not have to call outside code, using the GDT may indeed be the best option.
Regards, Carl-Daniel