Trouble with extern variable in 64 bit flat binary

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
jcmatias
Posts: 11
Joined: Mon Nov 08, 2004 12:00 am
Location: Ribeirao Preto SP Brasil

Trouble with extern variable in 64 bit flat binary

Post by jcmatias »

Enviorment : Linux Fedora 20
gcc version 4.8.3 20140624 (Red Hat 4.8.3-1)

my makefile is mk
my linker srcipt is LinkerScript_02

I have declared a var x as extern in test.h

define x in test.c

use make -f mk test.bin flat binary

disasemble it with ndisasm -b 64 test.bin >> test.nds

file test.h:

extern unsigned long int x ;

------------------------------
file test.c:

#include "test.h"

__attribute__((section(".data"))) unsigned long int x = 0x123456789abcdef;


void *_start(void)
{
unsigned long y = 0x123456789ABCDEF;


x = (unsigned long)&y;

return((void*)x);

}

------------------
make file
file mk:

CC = gcc

SOURCES = test.c

OBJ = test.o

BIN = test.bin

#use this to intel syntax
CFLAGS = -masm=intel -m64 -fno-builtin -nodefaultlibs -nostdinc -nostdlib -nostartfiles -fno-exceptions -fno-stack-protector -s -O2

#liker options
LFLAGS = -fdce -fdse -free -pie -fpic -s -static -T LinkerScript_02 -nostartfiles -nostdlib -nostdinc -nodefaultlibs -Wl,--oformat,binary -Wl,-e0x0 -Wl,-N -Wl,-q

$(BIN): $(OBJ)
$(CC) $(LFLAGS) $(OBJ) -o $(BIN)


$(OBJ): $(SOURCES)
$(CC) $(CFLAGS) $(SOURCES) -o $(OBJ)

--------------
Linker script
file LinkerScript_02:

ENTRY(start)

start = 0x0;

OUTPUT_FORMAT(binary)

SECTIONS
{
. = 0x0;

.text . :
{

*(.text) ;

}


.data . :
{
*(.data) *(.rodata) *(.bss) *(COMMON)
}



/DISCARD/ : { *(.got.plt) *(.shstrtab) *(.note.gnu.build-id ) *(.xdata) *(.pdata) *(.comment) *(.note.GNU-stack) *(.eh_frame) *(.eh_frame_hdr) }
}

---------------------------------------------------
make -f mk procuces test.bin


ndisasm -b 64 test.bin >> test.nds
-------------------------------------
test.nds:
disasembled code:

00000000 488D4424F8 lea rax,[rsp-0x8]
00000005 488905740E2000 mov [rel 0x200e80],rax
0000000C C3 ret
0000000D 0000 add [rax],al
0000000F 00EF add bh,ch
00000011 CDAB int 0xab
00000013 896745 mov [rdi+0x45],esp
00000016 2301 and eax,[rcx]

note : x address is 0x200e80 +IP
x value is stored at 0x11

I expected x addess at 0x11

How I can set the address of x to 0x11 ??
User avatar
sortie
Member
Member
Posts: 931
Joined: Wed Mar 21, 2012 3:01 pm
Libera.chat IRC: sortie

Re: Trouble with extern variable in 64 bit flat binary

Post by sortie »

You are using a very weird, unsupported and heavily discouraged approach. In particular, you are not using a cross-compiler, you are using a flat binary (they are too simple), you are passing a lot of options (some of them are bad) to the compiler and linker, you are putting variables in the .data section even though that's the default, you are changing the assembler language the compiler emits, and a lot of things I have never seen before (and I've seen quite some stuff).

It might be possible to osdev with your approach, but if you have to ask, then you are not able to do it. I expect your approach to give a lot of trouble and fall apart very soon, even if you get it working. I'm curious, where did you get the instructions to do these things?

I recommend you discard your code and follow http://wiki.osdev.org/Bare_Bones instead, or any other community reviewed and recommended approach.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Trouble with extern variable in 64 bit flat binary

Post by Brendan »

Hi,
jcmatias wrote:LFLAGS = -fdce -fdse -free -pie -fpic -s -static -T LinkerScript_02 -nostartfiles -nostdlib -nostdinc -nodefaultlibs -Wl,--oformat,binary -Wl,-e0x0 -Wl,-N -Wl,-q
I don't think it makes sense to ask for a position independent executable that is flat binary and has no GOT. As far as I know, this combination would be impossible to support.

For a simple example, imagine these global variables:

Code: Select all

int foo = 123;
int *fooPtr = &foo;
In this case, the compiler/linker has to give "fooPtr" a value (and can't rely on RIP relative addressing), but that value can't be known (due to position independence), so the GOT is required.

I also don't think it makes sense to ask for both PIC and PIE. Either it's an executable and not a library (and therefore PIC doesn't make sense) or it's a library and not an executable (and therefore PIE doesn't make sense). Note that for PIC/libraries the sizes of sections aren't known until the resulting library is linked into an executable; which means that the relative offset in an instruction like "mov [rel 0x200e80],rax" can't be known for PIC - this relative offset would have to be fixed later (when the library becomes an executable, and when the sizes of sections can be known).


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
no92
Member
Member
Posts: 307
Joined: Wed Oct 30, 2013 1:57 pm
Libera.chat IRC: no92
Location: Germany
Contact:

Re: Trouble with extern variable in 64 bit flat binary

Post by no92 »

Please use code-tags. It makes the code parts stand out and more readable.

As sortie pointed out, you are not using a cross-compiler and flat binaries. As Combuster said a while ago, "t tends to bite afterwards". Build one yourself using the wiki. After that, we'll be able to talk a little bit more.
jcmatias
Posts: 11
Joined: Mon Nov 08, 2004 12:00 am
Location: Ribeirao Preto SP Brasil

Re: Trouble with extern variable in 64 bit flat binary

Post by jcmatias »

Mr Brendan:
I try by any meas avoid relocation, but I think that you confirm my worst scenario.

I'm working in a scheme interpreter that run in pure metal : PC boots, goto long mode,
run the loop eval. I implement r6rs grammar in bison that generate yyparse()
and a lexer, yylex() , with re2c. A smal nunber of i/o funcitons (get puts,printf,string funcions)
was implemented too.
The pareser yypareser(), runs OK, but i have trouble wthi O N L Y one variable: yylval
yylval is extern. The entire program works well.
I don't want rewrite all parser ( the grammar is easy), but I refuse to lost to ONLY ONE variable.
If I had succes I will document all precess and post here.( I cant put nothin now, the code is very messy)

I copy the linker script from my original project that works like "Natural Selecion":
If works and dont disrupts keep, otherwise write off, so same flags are useless.
This is a test of concept.


But, same results that I expected are achived only with this freak combination of flags:
For example: Without -O2 my printf don't work properly with const strings:
char *hello="Hello, World" , printf("%s",hello) works, but printf("Hello, world") don't.
(before I post the code I will solve this);

This line for example __attribute__((section(".data"))) unsigned long int x = 0x123456789abcdef; is
attempt to put the varable in data section, but only the value goto .data section as we see at end of
disassembled code.
jcmatias
Posts: 11
Joined: Mon Nov 08, 2004 12:00 am
Location: Ribeirao Preto SP Brasil

Re: Trouble with extern variable in 64 bit flat binary

Post by jcmatias »

Solved :
As every people warned, the command line args to linker and compiler are wrong.
I will post a solution when I clean up the code.
Thanks for all !
Post Reply