|
@@ -3,10 +3,15 @@
|
|
|
/* a.out file reading ... */
|
|
|
|
|
|
#include "rd.h"
|
|
|
+#include "misc.h"
|
|
|
+#include <assert.h>
|
|
|
+#include <alloc.h>
|
|
|
|
|
|
#if defined(__sun)
|
|
|
+#if ! defined(sun)
|
|
|
#define sun
|
|
|
#endif
|
|
|
+#endif
|
|
|
|
|
|
#if defined(__i386)
|
|
|
#define i386
|
|
@@ -17,13 +22,20 @@
|
|
|
#endif
|
|
|
|
|
|
#if defined(__sparc)
|
|
|
+#if ! defined(sparc)
|
|
|
#define sparc
|
|
|
#endif
|
|
|
+#endif
|
|
|
|
|
|
#if defined(__vax)
|
|
|
#define vax
|
|
|
#endif
|
|
|
|
|
|
+#if defined(__solaris) || defined(__solaris__)
|
|
|
+#define solaris
|
|
|
+#endif
|
|
|
+
|
|
|
+#if ! defined(solaris)
|
|
|
#if defined(sun) || defined(vax)
|
|
|
|
|
|
struct exec {
|
|
@@ -215,6 +227,7 @@ rd_close()
|
|
|
fclose(inf);
|
|
|
}
|
|
|
|
|
|
+#endif
|
|
|
#endif
|
|
|
|
|
|
#if defined(i386)
|
|
@@ -380,3 +393,248 @@ rd_close()
|
|
|
{
|
|
|
}
|
|
|
#endif
|
|
|
+
|
|
|
+#if defined(solaris)
|
|
|
+#include <libelf.h>
|
|
|
+#include <sys/elf_M32.h>
|
|
|
+#include <stb.h>
|
|
|
+
|
|
|
+struct nlist {
|
|
|
+ union {
|
|
|
+ char *n_name;
|
|
|
+ long n_strx;
|
|
|
+ } n_un;
|
|
|
+ unsigned char n_type;
|
|
|
+ char n_other;
|
|
|
+ short n_desc;
|
|
|
+ unsigned long n_value;
|
|
|
+};
|
|
|
+
|
|
|
+static int fildes;
|
|
|
+static Elf *elf;
|
|
|
+static Elf32_Ehdr *ehdr;
|
|
|
+static struct nlist *dbtab;
|
|
|
+static char *dbstringtab;
|
|
|
+static Elf32_Sym *tab;
|
|
|
+static char *stringtab;
|
|
|
+static struct outhead hh;
|
|
|
+static struct nlist *maxdn;
|
|
|
+
|
|
|
+#define N_STAB 0xe0
|
|
|
+
|
|
|
+int
|
|
|
+rd_open(f)
|
|
|
+ char *f;
|
|
|
+{
|
|
|
+ if ((fildes = open(f, 0)) < 0) return 0;
|
|
|
+ elf_version(EV_CURRENT);
|
|
|
+ if ((elf = elf_begin(fildes, ELF_C_READ, (Elf *) 0)) == 0) {
|
|
|
+ close(fildes);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if ((ehdr = elf32_getehdr(elf)) == NULL) {
|
|
|
+ elf_end(elf);
|
|
|
+ close(fildes);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+rd_ohead(h)
|
|
|
+ struct outhead *h;
|
|
|
+{
|
|
|
+ Elf_Scn *scn = 0;
|
|
|
+ Elf32_Shdr *shdr;
|
|
|
+ Elf_Data *sectnames;
|
|
|
+ Elf_Data *dt;
|
|
|
+ register struct nlist *dn;
|
|
|
+ register Elf32_Sym *n;
|
|
|
+ long text_offset, data_offset, bss_offset, fun_offset;
|
|
|
+ int fixnamoff = 0, newfixnamoff = 0;
|
|
|
+
|
|
|
+ h->oh_magic = O_CONVERTED;
|
|
|
+ h->oh_stamp = 0;
|
|
|
+ h->oh_nsect = 4;
|
|
|
+ h->oh_nrelo = 0;
|
|
|
+ h->oh_flags = 0;
|
|
|
+ h->oh_nemit = 0;
|
|
|
+ h->oh_nname = 0;
|
|
|
+
|
|
|
+ scn = elf_getscn(elf, (size_t) ehdr->e_shstrndx);
|
|
|
+ sectnames = elf_getdata(scn, (Elf_Data *) 0);
|
|
|
+
|
|
|
+ scn = 0;
|
|
|
+ while ((scn = elf_nextscn(elf, scn)) != 0) {
|
|
|
+ shdr = elf32_getshdr(scn);
|
|
|
+ switch(shdr->sh_type) {
|
|
|
+ case SHT_PROGBITS:
|
|
|
+ /* Get stab symbol table. Elf does not know about it,
|
|
|
+ and, unfortunately, no relocation is done on it.
|
|
|
+ */
|
|
|
+ h->oh_nemit += shdr->sh_size;
|
|
|
+ if (! strcmp(".stab", (char *)(sectnames->d_buf)+shdr->sh_name)) {
|
|
|
+ dt = elf_getdata(scn, (Elf_Data *) 0);
|
|
|
+ if (dt->d_size == 0) {
|
|
|
+ fatal("(part of) symbol table is missing");
|
|
|
+ }
|
|
|
+ dbtab = (struct nlist *) Malloc(dt->d_size);
|
|
|
+ memcpy((char *) dbtab, (char *) dt->d_buf, dt->d_size);
|
|
|
+ maxdn = (struct nlist *)((char *)dbtab+dt->d_size);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case SHT_STRTAB:
|
|
|
+ /* Get the stab string table, as well as the usual string
|
|
|
+ table.
|
|
|
+ */
|
|
|
+ if (! strcmp(".stabstr", (char *)(sectnames->d_buf)+shdr->sh_name)) {
|
|
|
+ dt = elf_getdata(scn, (Elf_Data *) 0);
|
|
|
+ if (dt->d_size == 0) {
|
|
|
+ fatal("(part of) symbol table is missing");
|
|
|
+ }
|
|
|
+ dbstringtab = dt->d_buf;
|
|
|
+ h->oh_nchar = dt->d_size;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (! strcmp(".strtab", (char *)(sectnames->d_buf)+shdr->sh_name)) {
|
|
|
+ dt = elf_getdata(scn, (Elf_Data *) 0);
|
|
|
+ if (dt->d_size == 0) {
|
|
|
+ fatal("(part of) symbol table is missing");
|
|
|
+ }
|
|
|
+ stringtab = dt->d_buf;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case SHT_SYMTAB:
|
|
|
+ /* Get the symbol table. */
|
|
|
+ if (! strcmp(".symtab", (char *)(sectnames->d_buf)+shdr->sh_name)) {
|
|
|
+ dt = elf_getdata(scn, (Elf_Data *) 0);
|
|
|
+ if (dt->d_size == 0) {
|
|
|
+ fatal("(part of) symbol table is missing");
|
|
|
+ }
|
|
|
+ tab = dt->d_buf;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Convert offsets in stab symbol table. */
|
|
|
+ n = tab;
|
|
|
+ dn = dbtab;
|
|
|
+ while (dn < maxdn) {
|
|
|
+ int i;
|
|
|
+
|
|
|
+ if (dn->n_un.n_strx) {
|
|
|
+ dn->n_un.n_strx += fixnamoff;
|
|
|
+ }
|
|
|
+ switch(dn->n_type) {
|
|
|
+ case 0:
|
|
|
+ fixnamoff = newfixnamoff;
|
|
|
+ newfixnamoff += dn->n_value;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case N_SO:
|
|
|
+ h->oh_nname++;
|
|
|
+ i = 0;
|
|
|
+ while (i < 3) {
|
|
|
+ while (stringtab[n->st_name] != 'B') n++;
|
|
|
+ if (! strcmp("Btext.text", &(stringtab[n->st_name]))) {
|
|
|
+ text_offset = n->st_value; i++;
|
|
|
+ }
|
|
|
+ else if (! strcmp("Bdata.data", &(stringtab[n->st_name]))) {
|
|
|
+ data_offset = n->st_value; i++;
|
|
|
+ }
|
|
|
+ else if (! strcmp("Bbss.bss", &(stringtab[n->st_name]))) {
|
|
|
+ bss_offset = n->st_value; i++;
|
|
|
+ }
|
|
|
+ n++;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case N_GSYM:
|
|
|
+ h->oh_nname++;
|
|
|
+ /* Fortunately, we don't use this in ACK, so we don't
|
|
|
+ have to handle it here. The problem is that we don't know
|
|
|
+ which segment it comes from.
|
|
|
+ */
|
|
|
+ break;
|
|
|
+
|
|
|
+ case N_STSYM:
|
|
|
+ h->oh_nname++;
|
|
|
+ dn->n_value += data_offset;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case N_LCSYM:
|
|
|
+ h->oh_nname++;
|
|
|
+ dn->n_value += bss_offset;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case N_FUN:
|
|
|
+ h->oh_nname++;
|
|
|
+ dn->n_value += text_offset;
|
|
|
+ fun_offset = dn->n_value;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case N_MAIN:
|
|
|
+ dn->n_value += text_offset;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case N_LBRAC:
|
|
|
+ case N_RBRAC:
|
|
|
+ case N_SLINE:
|
|
|
+ h->oh_nname++;
|
|
|
+ dn->n_value += fun_offset;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case N_SOL:
|
|
|
+ case N_EINCL:
|
|
|
+ case N_BINCL:
|
|
|
+ case N_PSYM:
|
|
|
+ case N_SSYM:
|
|
|
+ case N_SCOPE:
|
|
|
+ case N_RSYM:
|
|
|
+ case N_LSYM:
|
|
|
+ h->oh_nname++;
|
|
|
+ /* Nothing to be done. */
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ dn++;
|
|
|
+ }
|
|
|
+ hh = *h;
|
|
|
+}
|
|
|
+
|
|
|
+rd_name(nm, count)
|
|
|
+ struct outname *nm;
|
|
|
+ unsigned int count;
|
|
|
+{
|
|
|
+ register struct nlist *dn = dbtab;
|
|
|
+ register struct outname *n = nm;
|
|
|
+ while (dn < maxdn) {
|
|
|
+ if (dn->n_type & N_STAB) {
|
|
|
+ n->on_type = dn->n_type << 8;
|
|
|
+ n->on_valu = dn->n_value;
|
|
|
+ n->on_desc = dn->n_desc;
|
|
|
+ if (dn->n_un.n_strx == 0) n->on_foff = 0;
|
|
|
+ else n->on_foff = OFF_CHAR(hh) + dn->n_un.n_strx;
|
|
|
+ n++;
|
|
|
+ }
|
|
|
+ dn++;
|
|
|
+ }
|
|
|
+ free(dbtab);
|
|
|
+}
|
|
|
+
|
|
|
+rd_string(nm, count)
|
|
|
+ char *nm;
|
|
|
+ long count;
|
|
|
+{
|
|
|
+ memcpy(nm, dbstringtab, count);
|
|
|
+}
|
|
|
+
|
|
|
+rd_close()
|
|
|
+{
|
|
|
+ elf_end(elf);
|
|
|
+ close(fildes);
|
|
|
+}
|
|
|
+
|
|
|
+#endif
|