diff options
Diffstat (limited to 'src/cmd/ld')
| -rw-r--r-- | src/cmd/ld/dwarf.c | 2 | ||||
| -rw-r--r-- | src/cmd/ld/elf.c | 80 | ||||
| -rw-r--r-- | src/cmd/ld/elf.h | 3 | ||||
| -rw-r--r-- | src/cmd/ld/lib.c | 16 | ||||
| -rw-r--r-- | src/cmd/ld/lib.h | 34 |
5 files changed, 134 insertions, 1 deletions
diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c index d21d05789c..add9277b36 100644 --- a/src/cmd/ld/dwarf.c +++ b/src/cmd/ld/dwarf.c @@ -812,7 +812,7 @@ enum vlong elfstrdbg[NElfStrDbg]; void -dwarfaddshstrings(Sym * shstrtab) +dwarfaddshstrings(Sym *shstrtab) { elfstrdbg[ElfStrDebugAbbrev] = addstring(shstrtab, ".debug_abbrev"); elfstrdbg[ElfStrDebugAranges] = addstring(shstrtab, ".debug_aranges"); diff --git a/src/cmd/ld/elf.c b/src/cmd/ld/elf.c index c5d58576dc..0ebdcf024c 100644 --- a/src/cmd/ld/elf.c +++ b/src/cmd/ld/elf.c @@ -21,6 +21,16 @@ static ElfPhdr *phdr[NSECT]; static ElfShdr *shdr[NSECT]; static char *interp; +typedef struct Elfstring Elfstring; +struct Elfstring +{ + char *s; + int off; +}; + +static Elfstring elfstr[100]; +static int nelfstr; + /* Initialize the global variable that describes the ELF header. It will be updated as we write section and prog headers. @@ -122,6 +132,18 @@ elfwriteshdrs(void) return hdr.shnum * ELF32SHDRSIZE; } +void +elfsetstring(char *s, int off) +{ + if(nelfstr >= nelem(elfstr)) { + diag("too many elf strings"); + errorexit(); + } + elfstr[nelfstr].s = s; + elfstr[nelfstr].off = off; + nelfstr++; +} + uint32 elfwritephdrs(void) { @@ -365,3 +387,61 @@ elfdynhash(int nsym) free(chain); free(buckets); } + +ElfPhdr* +elfphload(Segment *seg) +{ + ElfPhdr *ph; + + ph = newElfPhdr(); + ph->type = PT_LOAD; + if(seg->rwx & 4) + ph->flags |= PF_R; + if(seg->rwx & 2) + ph->flags |= PF_W; + if(seg->rwx & 1) + ph->flags |= PF_X; + ph->vaddr = seg->vaddr; + ph->paddr = seg->vaddr; + ph->memsz = seg->len; + ph->off = seg->fileoff; + ph->filesz = seg->filelen; + ph->align = INITRND; + + return ph; +} + +ElfShdr* +elfshbits(Section *sect) +{ + int i, off; + ElfShdr *sh; + + for(i=0; i<nelfstr; i++) { + if(strcmp(sect->name, elfstr[i].s) == 0) { + off = elfstr[i].off; + goto found; + } + } + diag("cannot find elf name %s", sect->name); + errorexit(); + return nil; + +found: + sh = newElfShdr(off); + if(sect->vaddr < sect->seg->vaddr + sect->seg->filelen) + sh->type = SHT_PROGBITS; + else + sh->type = SHT_NOBITS; + sh->flags = SHF_ALLOC; + if(sect->rwx & 1) + sh->flags |= SHF_EXECINSTR; + if(sect->rwx & 2) + sh->flags |= SHF_WRITE; + sh->addr = sect->vaddr; + sh->addralign = PtrSize; + sh->size = sect->len; + sh->off = sect->seg->fileoff + sect->vaddr - sect->seg->vaddr; + + return sh; +} diff --git a/src/cmd/ld/elf.h b/src/cmd/ld/elf.h index 9b5fdb17e9..41a6b39669 100644 --- a/src/cmd/ld/elf.h +++ b/src/cmd/ld/elf.h @@ -965,6 +965,9 @@ extern int iself; int elfwriteinterp(void); void elfinterp(ElfShdr*, uint64, char*); void elfdynhash(int); +ElfPhdr* elfphload(Segment*); +ElfShdr* elfshbits(Section*); +void elfsetstring(char*, int); /* * Total amount of space to reserve at the start of the file diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c index c91705c6ba..0cdc6778fc 100644 --- a/src/cmd/ld/lib.c +++ b/src/cmd/ld/lib.c @@ -908,3 +908,19 @@ mangle(char *file) fprint(2, "%s: mangled input file\n", file); errorexit(); } + +Section* +addsection(Segment *seg, char *name, int rwx) +{ + Section **l; + Section *sect; + + for(l=&seg->sect; *l; l=&(*l)->next) + ; + sect = mal(sizeof *sect); + sect->rwx = rwx; + sect->name = name; + sect->seg = seg; + *l = sect; + return sect; +} diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h index 501b6a2cbc..092161e14b 100644 --- a/src/cmd/ld/lib.h +++ b/src/cmd/ld/lib.h @@ -40,6 +40,34 @@ struct Library char *pkg; // import path }; +// Terrible but standard terminology. +// A segment describes a block of file to load into memory. +// A section further describes the pieces of that block for +// use in debuggers and such. + +typedef struct Segment Segment; +typedef struct Section Section; + +struct Segment +{ + uchar rwx; // permission as usual unix bits (5 = r-x etc) + uvlong vaddr; // virtual address + uvlong len; // length in memory + uvlong fileoff; // file offset + uvlong filelen; // length on disk + Section* sect; +}; + +struct Section +{ + uchar rwx; + char *name; + uvlong vaddr; + uvlong len; + Section *next; // in segment list + Segment *seg; +}; + extern char symname[]; extern char *libdir[]; extern int nlibdir; @@ -65,8 +93,14 @@ EXTERN char* outfile; EXTERN int32 nsymbol; EXTERN char* thestring; +EXTERN Segment segtext; +EXTERN Segment segdata; +EXTERN Segment segrodata; // NaCl only +EXTERN Segment segsym; + void addlib(char *src, char *obj); void addlibpath(char *srcref, char *objref, char *file, char *pkg); +Section* addsection(Segment*, char*, int); void copyhistfrog(char *buf, int nbuf); void addhist(int32 line, int type); void histtoauto(void); |
