]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
ELF uaedbg support.
authorToni Wilen <twilen@winuae.net>
Sat, 23 Feb 2019 14:54:12 +0000 (16:54 +0200)
committerToni Wilen <twilen@winuae.net>
Sat, 23 Feb 2019 14:54:12 +0000 (16:54 +0200)
debugmem.cpp
filesys.cpp
include/debugmem.h

index ba7802ad7672e1e0cafbde7ad996d7a434f20f80..b6baf4289701c35cc3a70015f8875be51305369e 100644 (file)
 #include "fsdb.h"
 #include "rommgr.h"
 
+#define ELFMODE_NORMAL 0
+#define ELFMODE_ROM 1
+#define ELFMODE_DEBUGMEM 2
+
 #define N_GSYM 0x20
 #define N_FUN 0x24
 #define N_STSYM 0x26
@@ -182,6 +186,7 @@ static int stackvarcnt;
 struct debugmemallocs
 {
        uae_u16 type;
+       TCHAR *name;
        uae_u32 id;
        uae_u16 internalid;
        uae_u32 parentid;
@@ -303,8 +308,12 @@ static void debugreportalloc(struct debugmemallocs *a)
 {
        uae_u32 off = debugmem_bank.start;
        if (a->type == DEBUGALLOC_HUNK) {
-               console_out_f(_T("Segment %d: %08x %08x - %08x (%d)\n"),
+               console_out_f(_T("Segment %d: %08x %08x - %08x (%d)"),
                        a->id, a->idtype, a->start + off, a->start + off + a->size - 1, a->size);
+               if (a->name) {
+                       console_out_f(_T(" %s"), a->name);
+               }
+               console_out_f(_T("\n"));
        } else if (a->type == DEBUGALLOC_ALLOCMEM) {
                console_out_f(_T("AllocMem ID=%4d: %08x %08x - %08x (%d) AllocFlags: %08x PC: %08x\n"),
                        a->id, a->idtype, a->start + off, a->start + off + a->size - 1, a->size, a->data, a->pc);
@@ -906,14 +915,17 @@ static struct debugmemallocs *debugmem_allocate(uae_u32 size, uae_u32 flags, uae
                memset(dm2->state, ((flags & DEBUGMEM_INITIALIZED) ? DEBUGMEM_INITIALIZED : 0) | DEBUGMEM_INUSE, PAGE_SIZE);
                uae_u8 filler = (flags & DEBUGMEM_INITIALIZED) ? 0x00 : 0x99;
                memset(debugmem_bank.baseaddr + (offset + startoffset + j) * PAGE_SIZE, filler, PAGE_SIZE);
-if (j == (size + PAGE_SIZE - 1) / PAGE_SIZE - 1) {
-       if (size & PAGE_SIZE_MASK) {
-               dm2->unused_end = PAGE_SIZE - (size & PAGE_SIZE_MASK);
-               dm2->flags |= DEBUGMEM_PARTIAL;
-               memset(dm2->state + (PAGE_SIZE - dm2->unused_end), 0, dm2->unused_end);
-               memset(debugmem_bank.baseaddr + (offset + startoffset + j) * PAGE_SIZE + (PAGE_SIZE - dm2->unused_end), 0x97, dm2->unused_end);
+               if (j == (size + PAGE_SIZE - 1) / PAGE_SIZE - 1) {
+                       if (size & PAGE_SIZE_MASK) {
+                               dm2->unused_end = PAGE_SIZE - (size & PAGE_SIZE_MASK);
+                               dm2->flags |= DEBUGMEM_PARTIAL;
+                               memset(dm2->state + (PAGE_SIZE - dm2->unused_end), 0, dm2->unused_end);
+                               memset(debugmem_bank.baseaddr + (offset + startoffset + j) * PAGE_SIZE + (PAGE_SIZE - dm2->unused_end), 0x97, dm2->unused_end);
+                       }
+               }
        }
-}
+       if (flags & DEBUGMEM_STACK) {
+               dm->name = my_strdup(_T("STACK"));
        }
        debugmemptr = offset * PAGE_SIZE + extrasize + ((size + PAGE_SIZE - 1) & ~PAGE_SIZE_MASK);
        return dm;
@@ -1416,7 +1428,7 @@ static void addsimplesymbol(const TCHAR *name, uae_u32 v, int type, int flags, i
 
        for (int i = 0; i < symbolcnt; i++) {
                struct debugsymbol *ds = symbols[i];
-               if (ds->segment == segmentid && !_tcscmp(name, ds->name))
+               if (ds->segment == segmentid && ds->name && !_tcscmp(name, ds->name))
                        return;
        }
        //write_log(_T("ELF Section %d, symbol %s=%08x\n"), segmentnum, name, v);
@@ -1562,24 +1574,13 @@ static uae_u8 *loadhunkfile(uae_u8 *file, int filelen, uae_u32 seglist, int segm
        return out;
 }
 
-uaecptr debugmem_reloc(uaecptr exeaddress, uae_u32 len, uaecptr task, uae_u32 *stack)
+static uaecptr loaddebugmemhunkfile(uae_u8 *p, uae_u32 len, uae_u32 *parentidp)
 {
-       uae_u8 *p = get_real_address(exeaddress);
        uae_u8 *lastptr = NULL;
        struct debugmemallocs *hunks[1000];
        uae_u32 lens[1000], memtypes[1000];
        uae_u32 parentid = 0;
 
-       debugmem_init(true);
-       if (!debugmem_initialized)
-               return 0;
-
-       console_out_f(_T("Loading executable, exe=%08x\n"), exeaddress);
-
-       if (gl(p) != 0x3f3) {
-               console_out_f(_T("HUNK_HEADER not found!\n"));
-               return 0;
-       }
        p += 4;
        if (gl(p) != 0) {
                console_out_f(_T("Long word after HUNK_HEADER is not zero!\n"));
@@ -1777,6 +1778,41 @@ uaecptr debugmem_reloc(uaecptr exeaddress, uae_u32 len, uaecptr task, uae_u32 *s
                console_out_f(_T("HUNK_END not found, got %08x\n"), gl(p - 4));
                return 0;
        }
+       *parentidp = parentid;
+       return hunks[first]->start;
+}
+
+static uae_u8 *loadelffile(uae_u8 *file, int filelen, uae_u8 *dbgfile, int debugfilelen, uae_u32 seglist, int segmentid, int *outsizep, uae_u32 *startp, uae_u32 *parentidp, int mode);
+
+uaecptr debugmem_reloc(uaecptr exeaddress, uae_u32 len, uaecptr dbgaddress, uae_u32 dbglen, uaecptr task, uae_u32 *stack)
+{
+       uae_u8 *p = get_real_address(exeaddress);
+       uae_u32 start;
+       uae_u32 parentid;
+
+       debugmem_init(true);
+       if (!debugmem_initialized)
+               return 0;
+
+       console_out_f(_T("Loading executable, exe=%08x\n"), exeaddress);
+
+       if (gl(p) == 0x7f454c46) {
+               uae_u8 *dp = NULL;
+               if (dbgaddress)
+                       dp = get_real_address(dbgaddress);
+               if (!loadelffile(p, len, dp, dbglen, 0, 0, NULL, &start, &parentid, ELFMODE_DEBUGMEM)) {
+                       return 0;
+               }
+       } else if (gl(p) == 0x000003f3) {
+               start = loaddebugmemhunkfile(p, len, &parentid);
+               if (!start) {
+                       return 0;
+               }
+       } else {
+               console_out_f(_T("Not executable! %02x%02x%02x%02x\n"), p[0], p[1], p[2], p[3]);
+               return 0;
+       }
+
        if (*stack) {
                struct debugmemallocs *stackmem = debugmem_allocate(*stack, DEBUGMEM_READ | DEBUGMEM_WRITE | DEBUGMEM_INITIALIZED | DEBUGMEM_STACK, parentid);
                if (!stackmem)
@@ -1810,7 +1846,7 @@ uaecptr debugmem_reloc(uaecptr exeaddress, uae_u32 len, uaecptr task, uae_u32 *s
        debug_task = task;
        debugmem_trace = true;
        debugmem_active = true;
-       return hunks[first]->start + debugmem_bank.start + 8;
+       return start + debugmem_bank.start + 8;
 }
 
 static uae_char *gethunktext(uae_u8 *p, uae_char *namebuf, int len)
@@ -2283,7 +2319,9 @@ struct debuglineheader
 #define R_68K_PC16      5
 #define R_68K_PC8       6
 
+#define SHF_WRITE              (1 << 0)
 #define SHF_ALLOC       (1 << 1)
+#define SHF_EXECINSTR  (1 << 2)
 
 static void wswp(uae_u16 *v)
 {
@@ -2338,31 +2376,45 @@ static void swap_rel(struct rel *d, struct rel *s)
        lswp(&d->offset);
 }
 
-static int loadelf(uae_u8 *file, int filelen, uae_u8 **outp, int outsize, uae_u32 addr, struct sheader *sh)
+static int loadelf(uae_u8 *file, int filelen, uae_u8 **outp, int outsize, struct sheader *sh)
 {
        int size = sh->size;
        uae_u8 *out = *outp;
-       if (!out)
-               out = xcalloc(uae_u8, outsize + size);
-       else
-               out = xrealloc(uae_u8, out, outsize + size);
+       if (outsize >= 0) {
+               if (!out)
+                       out = xcalloc(uae_u8, outsize + size);
+               else
+                       out = xrealloc(uae_u8, out, outsize + size);
+       } else {
+               outsize = 0;
+       }
        memcpy(out + outsize, file + sh->offset, size);
        outsize += size;
        *outp = out;
        return outsize;
 }
 
-static uae_u8 *loadelffile(uae_u8 *file, int filelen, uae_u32 seglist, int segmentid, int *outsizep, bool rommode)
+struct loadelfsection
+{
+       uae_u32 offsets;
+       uae_u32 bases;
+       struct debugmemallocs *dma;
+};
+
+static uae_u8 *loadelffile(uae_u8 *file, int filelen, uae_u8 *dbgfile, int debugfilelen, uae_u32 seglist, int segmentid, int *outsizep, uae_u32 *startp, uae_u32 *parentidp, int mode)
 {
        uae_u8 *outp = NULL;
        uae_u8 *outptr = NULL;
        int outsize;
-       bool relocate = rommode;
+       bool relocate = false;
        uae_u32 relocate_base = 0;
 
        struct elfheader *eh = (struct elfheader*)file;
        uae_u8 *p = file + sizeof(struct elfheader);
 
+       if (mode != ELFMODE_NORMAL)
+               relocate = true;
+
        wswp(&eh->type);
        wswp(&eh->machine);
        wswp(&eh->ehsize);
@@ -2399,6 +2451,7 @@ static uae_u8 *loadelffile(uae_u8 *file, int filelen, uae_u32 seglist, int segme
        int debugstr_size;
        int debugabbrev_size;
        int symtab_num = 0;
+
        for (int i = 0; i < shnum; i++) {
                struct sheader *shp = (struct sheader*)(file + i * sizeof(sheader) + eh->shoff);
                struct sheader sh;
@@ -2444,42 +2497,68 @@ static uae_u8 *loadelffile(uae_u8 *file, int filelen, uae_u32 seglist, int segme
        int section = -1;
        uae_u32 seg = seglist * 4;
        uae_u32 nextseg = 0;
+       uae_u32 parentid = 0;
+       int startseg = -1;
 
-       uae_u32 *sectionoffsets = xcalloc(uae_u32, shnum);
-       uae_u32 *sectionbases = xcalloc(uae_u32, shnum);
+       struct loadelfsection *lelfs = xcalloc(struct loadelfsection, shnum);
        outsize = 0;
        for (int i = 0; i < shnum; i++) {
                struct sheader *shp = (struct sheader*)&shp_first[i];
                struct sheader sh;
                swap_header(&sh, shp);
-               sectionoffsets[i] = 0xffffffff;
-               sectionbases[i] = 0xffffffff;
+               lelfs[i].offsets = 0xffffffff;
+               lelfs[i].bases = 0xffffffff;
                uae_char *namep = (uae_char*)(strtabsym + sh.name);
                TCHAR *n = au(namep);
                write_log(_T("ELF section %d: type=%08x flags=%08x size=%08x ('%s')\n"), i, sh.type, sh.flags, sh.size, n);
-               xfree(n);
                if (sh.type == SHT_PROGBITS) {
                        if ((sh.flags & SHF_ALLOC) && sh.size) {
                                write_log(_T(" - load data. Offset %08x\n"), outsize);
-                               sectionoffsets[i] = outsize;
-                               if (relocate)
-                                       sectionbases[i] = outsize;
+                               if (startseg < 0)
+                                       startseg = i;
+                               if (mode == ELFMODE_DEBUGMEM) {
+                                       struct debugmemallocs *dma = debugmem_allocate(sh.size + 8,
+                                               DEBUGMEM_READ | ((sh.flags & SHF_WRITE) ? DEBUGMEM_WRITE : 0) | ((sh.flags & SHF_EXECINSTR) ? DEBUGMEM_FETCH : 0)  | DEBUGMEM_INITIALIZED, parentid);
+                                       lelfs[i].dma = dma;
+                               } else {
+                                       lelfs[i].offsets = outsize;
+                                       if (relocate)
+                                               lelfs[i].bases = outsize;
+                               }
                                outsize += sh.size;
                        }
                } else if (sh.type == SHT_NOBITS) {
                        if (sh.size) {
-                               sectionbases[i] = sh.addr;
+                               lelfs[i].bases = sh.addr;
+                               write_log(_T(" - bss. Offset %08x\n"), outsize);
+                               if (mode == ELFMODE_DEBUGMEM) {
+                                       struct debugmemallocs *dma = debugmem_allocate(sh.size + 8, DEBUGMEM_READ | ((sh.flags & SHF_WRITE) ? DEBUGMEM_WRITE : 0) | DEBUGMEM_INITIALIZED, parentid);
+                                       lelfs[i].dma = dma;
+                               }
+                       }
+               }
+               if (lelfs[i].dma) {
+                       struct debugmemallocs *dma = lelfs[i].dma;
+                       lelfs[i].offsets = dma->start + debugmem_bank.start + 8;
+                       lelfs[i].bases = dma->start + debugmem_bank.start + 8;
+                       dma->type = DEBUGALLOC_HUNK;
+                       dma->relative_start = dma->start;
+                       dma->idtype = sh.type;
+                       dma->name = my_strdup(n);
+                       if (!parentid) {
+                               parentid = dma->id;
                        }
                }
+               xfree(n);
        }
 
-       if (rommode) {
+       if (mode == ELFMODE_ROM) {
                relocate_base = getrombase(outsize);
                if (!relocate_base)
                        goto end;
                for (int i = 0; i < shnum; i++) {
-                       if (sectionoffsets[i] != 0xffffffff)
-                               sectionbases[i] += relocate_base;
+                       if (lelfs[i].offsets != 0xffffffff)
+                               lelfs[i].bases += relocate_base;
                }
        }
 
@@ -2506,14 +2585,14 @@ static uae_u8 *loadelffile(uae_u8 *file, int filelen, uae_u32 seglist, int segme
                        continue;
                }
                if (sym.shindex == SHN_ABS) {
-                       uae_char *namep = (uae_char*)(strtabsym + sym.name);
+                       uae_char *namep = (uae_char*)(strtab + sym.name);
                        TCHAR *name = au(namep);
                        addsimplesymbol(name, sym.value, stype, sflags, segmentid, sym.shindex);
                        xfree(name);
-               } else if (sym.shindex < shnum && sectionoffsets[sym.shindex] != 0xffffffff) {
-                       uae_char *namep = (uae_char*)(strtabsym + sym.name);
+               } else if (sym.shindex < shnum && lelfs[sym.shindex].offsets != 0xffffffff) {
+                       uae_char *namep = (uae_char*)(strtab + sym.name);
                        TCHAR *name = au(namep);
-                       uae_u32 v = sym.value + sectionbases[sym.shindex];
+                       uae_u32 v = sym.value + lelfs[sym.shindex].bases;
                        addsimplesymbol(name, v, stype, sflags, segmentid, sym.shindex);
                        xfree(name);
                }
@@ -2531,7 +2610,7 @@ static uae_u8 *loadelffile(uae_u8 *file, int filelen, uae_u32 seglist, int segme
                        nextseg = 0;
                }
 
-               sectionoffsets[i] = outsize;
+               lelfs[i].offsets = outsize;
 
                if (sh.type == SHT_NOBITS) {
                        outptr = NULL;
@@ -2550,10 +2629,17 @@ static uae_u8 *loadelffile(uae_u8 *file, int filelen, uae_u32 seglist, int segme
                                if (seg)
                                        nextseg = get_long(seg) * 4;
                                if (relocate) {
-                                       int newoutsize = loadelf(file, filelen, &outp, outsize, relocate_base, &sh);
-                                       outptr = outp + outsize;
-                                       outsize = newoutsize;
-                                       *outsizep = outsize;
+                                       if (mode == ELFMODE_DEBUGMEM) {
+                                               uae_u8 *mem = lelfs[i].dma->start + debugmem_bank.baseaddr + 8;
+                                               outp = mem;
+                                               outptr = mem;
+                                               loadelf(file, filelen, &outp, -1, &sh);
+                                       } else {
+                                               int newoutsize = loadelf(file, filelen, &outp, outsize, &sh);
+                                               outptr = outp + outsize;
+                                               outsize = newoutsize;
+                                               *outsizep = outsize;
+                                       }
                                }
                        }
                        continue;
@@ -2626,10 +2712,10 @@ static uae_u8 *loadelffile(uae_u8 *file, int filelen, uae_u32 seglist, int segme
                                }
                                default:
                                {
-                                       if (sectionbases[shindex] == 0xffffffff) {
+                                       if (lelfs[shindex].bases == 0xffffffff) {
                                                s = 0;
                                        } else {
-                                               s = sectionbases[shindex] + sym.value;
+                                               s = lelfs[shindex].bases + sym.value;
                                                doreloc = true;
                                        }
                                        break;
@@ -2665,7 +2751,7 @@ static uae_u8 *loadelffile(uae_u8 *file, int filelen, uae_u32 seglist, int segme
                                        has = true;
                                        break;
                                case R_68K_PC32:
-                                       addr = s + rel.addend - (sectionbases[shindex] + relocaddr);
+                                       addr = s + rel.addend - (lelfs[shindex].bases + relocaddr);
                                        if (outptr) {
                                                outptr[relocaddr + 0] = (uae_u8)(addr >> 24);
                                                outptr[relocaddr + 1] = (uae_u8)(addr >> 16);
@@ -2675,7 +2761,7 @@ static uae_u8 *loadelffile(uae_u8 *file, int filelen, uae_u32 seglist, int segme
                                        has = true;
                                        break;
                                case R_68K_PC16:
-                                       addr = s + rel.addend - (sectionbases[shindex] + relocaddr);
+                                       addr = s + rel.addend - (lelfs[shindex].bases + relocaddr);
                                        if (outptr) {
                                                outptr[relocaddr + 0] = (uae_u8)(addr >> 8);
                                                outptr[relocaddr + 1] = (uae_u8)(addr >> 0);
@@ -2683,7 +2769,7 @@ static uae_u8 *loadelffile(uae_u8 *file, int filelen, uae_u32 seglist, int segme
                                        has = true;
                                        break;
                                case R_68K_PC8:
-                                       addr = s + rel.addend - (sectionbases[shindex] + relocaddr);
+                                       addr = s + rel.addend - (lelfs[shindex].bases + relocaddr);
                                        if (outptr) {
                                                outptr[relocaddr] = (uae_u8)addr;
                                        }
@@ -2826,8 +2912,11 @@ static uae_u8 *loadelffile(uae_u8 *file, int filelen, uae_u32 seglist, int segme
 #endif
 
 end:
-       xfree(sectionoffsets);
-       xfree(sectionbases);
+       xfree(lelfs);
+       if (startp && startseg >= 0)
+               *startp = lelfs[startseg].dma->start;
+       if (parentidp)
+               *parentidp = parentid;
        return outp;
 }
 
@@ -2934,9 +3023,9 @@ void debugmem_addsegs(TrapContext *ctx, uaecptr seg, uaecptr name, uae_u32 lock,
        }
 
        if (elfsymfile) {
-               loadelffile(symfile, symfilelen, seg, segmentid, NULL, false);
+               loadelffile(symfile, symfilelen, NULL, 0, seg, segmentid, NULL, NULL, NULL, ELFMODE_NORMAL);
        } else if (elffile) {
-               loadelffile(file, filelen, seg, segmentid, NULL, false);
+               loadelffile(file, filelen, NULL, 0, seg, segmentid, NULL, NULL, NULL, ELFMODE_NORMAL);
        }
 
        int parentid = 0;
@@ -3296,6 +3385,7 @@ void debugmem_init(bool initmem)
                codefiles = xcalloc(struct debugcodefile*, MAX_DEBUGCODEFILES);
        }
        for (int i = 0; i < MAX_DEBUGMEMALLOCS; i++) {
+               xfree(allocs[i]->name);
                memset(allocs[i], 0, sizeof(struct debugmemallocs));
        }
        for (int i = 0; i < totalmemdata; i++) {
@@ -3535,6 +3625,8 @@ int debugmem_get_sourceline(uaecptr addr, TCHAR *out, int maxsize)
                        int offset = addr - alloc->start + alloc->relative_start - 8;
                        if (offset < 0)
                                return -1;
+                       if (offset >= linemapsize)
+                               return -1;
                        struct linemapping *lm = &linemap[offset];
                        int line = lm->line;
                        if (line < 0)
@@ -3820,7 +3912,7 @@ struct zfile *read_executable_rom(struct zfile *z, int size, int maxblocks)
        zfile_fread(header, 1, sizeof(header), z);
        zfile_fseek(z, 0, SEEK_SET);
        if (header[0] == 0x7f)
-               out = loadelffile(file, len, 0, -1, &outlen, true);
+               out = loadelffile(file, len, NULL, 0, 0, -1, &outlen, NULL, NULL, ELFMODE_ROM);
        else
                out = loadhunkfile(file, len, 0, -1, &outlen, true);
        if (out) {
index 447e1ead8ede30021f596bfeaa2826e52ccbae60..4b0fee3df562699cccdfb96a6bca7021ba90da4d 100644 (file)
@@ -8956,9 +8956,17 @@ static uae_u32 REGPARAM2 mousehack_done (TrapContext *ctx)
                trap_put_long(ctx, trap_get_areg(ctx, 7) + 4 * 4, ret);
        } else if (mode == 200) {
                uae_u32 v;
-               // a0 = data, d0 = length, a1 = task, d2 = stack size (in), stack ptr (out)
-               uae_u32 stack = trap_get_dreg(ctx, 2);
-               v = debugmem_reloc(trap_get_areg(ctx, 0), trap_get_dreg(ctx, 0), trap_get_areg(ctx, 1), &stack);
+               // a0 = data, d0 = length, a1 = task, d3 = stack size (in), stack ptr (out)
+               // a2 = debugdata, d2 = debuglength
+               // d4 = flags
+               if ((trap_get_dreg(ctx, 4) & 3) != 1) {
+                       write_log(_T("unsupported uaedbg version\n"));
+                       return 0;
+               }
+               uae_u32 stack = trap_get_dreg(ctx, 3);
+               v = debugmem_reloc(trap_get_areg(ctx, 0), trap_get_dreg(ctx, 0),
+                       trap_get_areg(ctx, 2), trap_get_dreg(ctx, 2),
+                       trap_get_areg(ctx, 1), &stack);
                trap_set_dreg(ctx, 2, stack);
                return v;
        } else if (mode == 201) {
index 4fc3be47aba50762a4a2a1be829cab863cb38c21..dc1d1c0d4f161d966e78ba351ea70827a33c2f9d 100644 (file)
@@ -1,5 +1,5 @@
 
-uaecptr debugmem_reloc(uaecptr exeaddress, uae_u32 len, uaecptr task, uae_u32 *stack);
+uaecptr debugmem_reloc(uaecptr exeaddress, uae_u32 len, uaecptr dbgaddress, uae_u32 dbglen, uaecptr task, uae_u32 *stack);
 void debugmem_init(bool);
 uaecptr debugmem_allocmem(int mode, uae_u32 size, uae_u32 flags, uae_u32 caller);
 uae_u32 debugmem_freemem(int mode, uaecptr addr, uae_u32 size, uae_u32 caller);