GNU linker scripts journey

first, we need to know about sections, lets take a look, nice stuff

lets start with make very simple library

// gcc -c libcall.c

extern int random_me;

/* this is .text section */
int lib_call(const char* str) {
        (void)str;

        /* this is .bss */
        static int im_counting;
        im_counting++;
}

then, run nm libcall.o image

as we can see, b (lowercase) means the bss section is not exported, while T (uppercase) means .text is exported. then, lets call lib_call function from run function (in other file), say the file is run.c which has contents

// gcc -c run.c
extern int  lib_call(const char* str);

void run(void) {
        /* this will be .data */
        static int data = 5;
        data = lib_call("im a .rodata");
}

again, we got this

image

the U uppercase is means, the lib_call is undefined. now how we can resolve it?

first, lets link run.o

> gcc run.o
/usr/bin/ld: /usr/lib/gcc/x86_64-pc-linux-gnu/15.1.1/../../../../lib/Scrt1.o: in function `_start':
(.text+0x1b): undefined reference to `main'
/usr/bin/ld: run.o: in function `run':
run.c:(.text+0xf): undefined reference to `lib_call'
collect2: error: ld returned 1 exit status

[ads] if you want automate it, use Makefile instead

CC = gcc

stage_1_libcall: libcall.c
	gcc -c libcall.c
	ar r libcall.a libcall.o


stage_2_run: run.c
	gcc -c run.c

stage_3: stage_1_libcall stage_2_run
	gcc run.o -L. -lcall -nostartfiles

clean:
	rm -f a.out
	rm -f libcall.a
	rm -f libcall.o
	rm -f run.o

back to linker, lets run make stage_3, and check for nm a.out. supraisingly, the lib_call is not undefined again. thanks for ld

image

objdump

image

ld

now, our task. how to rearrange this order. lets create our link.ld

ENTRY(run) 
SECTIONS {
    .text : {
        *(.text);
        *(.text.*)
    }

    .bss : {
        *(.bss);
        *(.bss.*)
    }

    .data : {
        *(.data);
        *(.data.*)
    }

    .rodata : {
        *(.rodata);
        *(.rodata.*)
    }
}

v2:

ENTRY(run)

PHDRS {
    text PT_LOAD FLAGS(5); /* RX */
    data PT_LOAD FLAGS(6); /* RW */
}

SECTIONS {
    . = 0x10000;

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

    .rodata : {
        *(.rodata);
        *(.rodata.*)
    } :text

    .data : {
        *(.data);
        *(.data.*)
    } :data

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