aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/ld
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/ld')
-rw-r--r--src/cmd/ld/dwarf.c2
-rw-r--r--src/cmd/ld/elf.c80
-rw-r--r--src/cmd/ld/elf.h3
-rw-r--r--src/cmd/ld/lib.c16
-rw-r--r--src/cmd/ld/lib.h34
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);