bebbo / binutils-gdb

Unofficial mirror of sourceware binutils-gdb repository. Updated daily.
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git
GNU General Public License v2.0
3 stars 3 forks source link

ld: refuses to perform partial linking #27

Open cahirwpz opened 1 year ago

cahirwpz commented 1 year ago

Partial linking is a useful feature of GNU ld that can be used to split single executable binary into several small loadable modules and use technique called Overlays. This could be extremely useful for demos (that is of main interest to me) and games that don't need to keep all executable code in memory at the same time. However currently m68k-amigaos-ld does not support that :(

Here's how I tested it:

Makefile file contents:

CC = m68k-amigaos-gcc
LD = m68k-amigaos-ld
CFLAGS = -g -O -Wall

all.o: a.o b.o c.o
    $(LD) -r -o $@ $^

a.o: a.c
b.o: b.c
c.o: c.c

clean:
    rm -f *.o *~

a.c file contents:

extern void printnum(int x);

int a(int x) {
  printnum(x);
  return x + 1;
}

b.c file contents:

extern int a(int);

extern int b_x;

int b(int x) {
  return a(x) * 2 + b_x;
}

c.c file contents:

extern int b(int);

int c(int x) {
  return b(x) & 7;
}

With current HEAD i.e. https://github.com/bebbo/binutils-gdb/commit/033085a1380353822c19adc1d9c9dadb82ba42e1 I get:

# make
m68k-amigaos-gcc -g -O -Wall   -c -o a.o a.c
m68k-amigaos-gcc -g -O -Wall   -c -o b.o b.c
m68k-amigaos-gcc -g -O -Wall   -c -o c.o c.c
m68k-amigaos-ld -r -o all.o a.o b.o c.o
m68k-amigaos-ld: final link failed: bad value
make: *** [all.o] Error 1

I would expect a single binary all.o to be created, for which nm would give me an output similar to the following:

T a
T b
U b_x
T c
U printnum
bebbo commented 1 year ago

if you omit the '-r' you get

m68k-amigaos-ld: a.o: in function `a':
/home/stefan/amiga-gcc/tickets/bu27/a.c:4: undefined reference to `printnum'
m68k-amigaos-ld: b.o: in function `b':
/home/stefan/amiga-gcc/tickets/bu27/b.c:7: undefined reference to `b_x'
bebbo commented 1 year ago

I guess with -r a new object file should be created combining the many files to one?

cahirwpz commented 1 year ago

Yes. That's exactly what I meant by partial linking. It's like linking several files into intermediate relocatable .o file.

bebbo commented 1 year ago

Yes. That's exactly what I meant by partial linking. It's like linking several files into intermediate relocatable .o file.

would it be sufficient just to combine all provided sections? Or what kind of linking should be done??

cahirwpz commented 1 year ago

I've installed gcc-10-m68k-linux-gnu to make sure what am I asking for :)

Let's see how a.o, b.o and c.o look like after disassembly with m68k-linux-gnu-objdump -d -r:

a.o:     file format elf32-m68k

Disassembly of section .text:

00000000 <a>:
   0:   2f02            movel %d2,%sp@-
   2:   242f 0008       movel %sp@(8),%d2
   6:   2f02            movel %d2,%sp@-
   8:   4eb9 0000 0000  jsr 0 <a>
            a: R_68K_32 printnum
   e:   588f            addql #4,%sp
  10:   2002            movel %d2,%d0
  12:   5280            addql #1,%d0
  14:   241f            movel %sp@+,%d2
  16:   4e75            rts
b.o:     file format elf32-m68k

Disassembly of section .text:

00000000 <b>:
   0:   2f2f 0004       movel %sp@(4),%sp@-
   4:   4eb9 0000 0000  jsr 0 <b>
            6: R_68K_32 a
   a:   d080            addl %d0,%d0
   c:   588f            addql #4,%sp
   e:   d0b9 0000 0000  addl 0 <b>,%d0
            10: R_68K_32    b_x
  14:   4e75            rts
c.o:     file format elf32-m68k

Disassembly of section .text:

00000000 <c>:
   0:   2f2f 0004       movel %sp@(4),%sp@-
   4:   4eb9 0000 0000  jsr 0 <c>
            6: R_68K_32 b
   a:   588f            addql #4,%sp
   c:   7207            moveq #7,%d1
   e:   c081            andl %d1,%d0
  10:   4e75            rts

And here's the output file:

all.o:     file format elf32-m68k

Disassembly of section .text:

00000000 <a>:
   0:   2f02            movel %d2,%sp@-
   2:   242f 0008       movel %sp@(8),%d2
   6:   2f02            movel %d2,%sp@-
   8:   4eb9 0000 0000  jsr 0 <a>
            a: R_68K_32 printnum
   e:   588f            addql #4,%sp
  10:   2002            movel %d2,%d0
  12:   5280            addql #1,%d0
  14:   241f            movel %sp@+,%d2
  16:   4e75            rts

00000018 <b>:
  18:   2f2f 0004       movel %sp@(4),%sp@-
  1c:   4eb9 0000 0000  jsr 0 <a>
            1e: R_68K_32    a
  22:   d080            addl %d0,%d0
  24:   588f            addql #4,%sp
  26:   d0b9 0000 0000  addl 0 <a>,%d0
            28: R_68K_32    b_x
  2c:   4e75            rts
  2e:   4e71            nop

00000030 <c>:
  30:   2f2f 0004       movel %sp@(4),%sp@-
  34:   4eb9 0000 0000  jsr 0 <a>
            36: R_68K_32    b
  3a:   588f            addql #4,%sp
  3c:   7207            moveq #7,%d1
  3e:   c081            andl %d1,%d0
  40:   4e75            rts

m68k-linux-gnu-nm a.o b.o c.o all.o gives:

a.o:
00000000 T a
         U printnum

b.o:
         U a
00000000 T b
         U b_x

c.o:
         U b
00000000 T c

all.o:
00000000 T a
00000018 T b
         U b_x
00000030 T c
         U printnum

So it seems that partial (or incremental) linking merges sections, performs partial symbol resolution and relocation.