October 22, 2024
Chicago 12, Melborne City, USA
C#

Linker Fails To Resolve External Pointer


I am trying to compile the following files using gcc (arm-linux-musleabi-gcc (GCC) 9.4.0), but the reference to json_start does not get fixed up correctly and incorrectly ends up as an offset rather than a pc relative access (ie. 0x4762 instead of 0x5114762).

The idea is that the json contents get binned into the binary. Ideally we would use the #embed directive but the musl build does not support that yet. We did also consider .incbin but we would prefer not to add an assembly file simply to handle something that objcopy already purports to support. Additionally I would like to understand what exactly is happening here.

file.h

#ifndef __FILE_H__
#define __FILE_H__
#include <stddef.h>


typedef size_t (*strlen_fn)(const char *s);
#define strlen ((strlen_fn)Strlen)

extern const unsigned char * json_start;
#endif

file.c:

#include <file.h>

void *entry(void) __attribute__((section(".entry")));
void do_stuff(unsigned char *, void *);


void *entry(void) {
    do_stuff((unsigned char *)json_start, entry);
}

void do_stuff(unsigned char *json_start, void *entry) {
    json_start[0] = 0;
    return;
}

file.json:

{}

linker.ld

SECTIONS
{
    .text : 
    {
        *(.entry)
        *(.core)
        *(.text*)
        *(.rodata*)
        *(.data*)
        *(.bss*)
        *(.got*)
        *(COMMON)
    }
    /DISCARD/ : 
    {
        *(*)
    }
}

Currently I’m trying:

rm -r build
mkdir -p ./build
arm-linux-musleabi-objcopy -I binary -B arm -O elf32-littlearm ./file.json ./build/json.o
arm-linux-musleabi-objcopy --redefine-sym _binary___file_json_start=json_start ./build/json.o
arm-linux-musleabi-gcc -o ./build/file.o -c -fPIE -fno-builtin -ffreestanding -march=armv5t -Os -I . file.c
arm-linux-musleabi-gcc -o ./build/file -nostdlib -pie -T linker.ld ./build/file.o ./build/json.o -lgcc

I have also tried:

arm-linux-musleabi-gcc -r -o ./build/json.o -Wl,-b,binary file.json
arm-linux-musleabi-objcopy --redefine-sym _binary_file_json_start=json_start ./build/json.o

which is no better.

The assembly ends up looking like:

ldr r3,[r3,r2]
ldr r0,[r3,#0x0]
bl do_stuff

rather than

ldr r3,[r3,r2]
ldr r0,[r3,#0x0]
add r0, pc, r0
bl do_stuff

where r0 is json_start.

UPDATE:

I have figured out that its because json_start ends up in the GOT. My linker script just bins the GOT into the binary and none of the symbols get fixed up.



You need to sign in to view this answers

Leave feedback about this

  • Quality
  • Price
  • Service

PROS

+
Add Field

CONS

+
Add Field
Choose Image
Choose Video