scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

elfgetsym.c (2182B)


      1 #include <ctype.h>
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <string.h>
      5 
      6 #include <scc/mach.h>
      7 #include <scc/elf/elftypes.h>
      8 #include <scc/elf/elfent.h>
      9 #include <scc/elf/elfshdr.h>
     10 #include <scc/elf.h>
     11 
     12 #include "../libmach.h"
     13 #include "fun.h"
     14 
     15 static int
     16 typeof(Elf *elf, Elfsym *ent, char *name)
     17 {
     18 	int c, bind, weak;
     19 	unsigned long flags, type;
     20 	Elfsec *shdr;
     21 
     22 	weak = ELF_ST_BIND(ent->info) == STB_WEAK;
     23 
     24 	switch (ent->shndx) {
     25 	case SHN_UNDEF:
     26 		c = 'U';
     27 		break;
     28 	case SHN_ABS:
     29 		c = 'a';
     30 		break;
     31 	case SHN_COMMON:
     32 		c = 'C';
     33 		break;
     34 	case SHN_XINDEX:
     35 		abort();
     36 	default:
     37 		shdr = &elf->secs[ent->shndx];
     38 		flags = shdr->flags;
     39 		type = shdr->type;
     40 
     41 		if (ELF_ST_BIND(ent->info) == STB_WEAK) {
     42 			c = (flags & SHF_EXECINSTR) ? 'W' : 'V';
     43 		} else {
     44 			if (flags & SHF_ALLOC) {
     45 				if (type == SHT_NOBITS)
     46 					c = 'b';
     47 				else if (flags & SHF_WRITE)
     48 					c = 'd';
     49 				else if (flags & SHF_EXECINSTR)
     50 					c = 't';
     51 				else
     52 					c = 'r';
     53 			} else if (strncmp(name, ".debug", 6) == 0) {
     54 				c = 'N';
     55 			} else if (strcmp(name, ".comment") == 0) {
     56 				c = 'N';
     57 			} else if (strcmp(name, ".line") == 0) {
     58 				c = 'N';
     59 			} else if (strcmp(name, ".stab") == 0) {
     60 				c = 'N';
     61 			} else {
     62 				c = '?';
     63 			}
     64 			if (ELF_ST_BIND(ent->info) != STB_LOCAL)
     65 				c = toupper(c);
     66 		}
     67 	}
     68 
     69 	return c;
     70 }
     71 
     72 static int
     73 stypeof(Elfsym *ent)
     74 {
     75 	switch (ELF_ST_TYPE(ent->info)) {
     76 	case STT_OBJECT:
     77 		return SYMOBJECT;
     78 	case STT_FUNC:
     79 		return SYMFUNC;
     80 	case STT_SECTION:
     81 		return SYMSECTION;
     82 	case STT_FILE:
     83 		return SYMFILE;
     84 	case STT_COMMON:
     85 		return SYMCOMMON;
     86 	default:
     87 	case STT_NOTYPE:
     88 		return SYMNOTYPE;
     89 	}
     90 }
     91 
     92 #include <assert.h>
     93 
     94 Symbol *
     95 elfgetsym(Obj *obj, int *idx, Symbol *sym)
     96 {
     97 	int n = *idx;
     98 	Elfsym *ent;
     99 	Elf *elf = obj->data;
    100 
    101 	if (n == 0)
    102 		n++;
    103 
    104 	if (!elf->syms || n >= elf->nsym)
    105 		return NULL;
    106 	ent = &elf->syms[n];
    107 
    108 	if (ELF_ST_TYPE(ent->info) == STT_SECTION) {
    109 		Elfsec *shdr = &elf->secs[ent->shndx];
    110 		sym->name = shdr->name;
    111 	} else {
    112 		sym->name = ent->name;
    113 	}
    114 
    115 	// assert(strlen(sym->name) > 0);
    116 	sym->type = typeof(elf, ent, sym->name);
    117 	sym->stype = stypeof(ent);
    118 	sym->value = ent->value;
    119 	sym->size = ent->size;
    120 	sym->index = *idx = n;
    121 
    122 	return sym;
    123 }