scc

A fork of https://git.simple-cc.org/scc/ for Qute

git clone https://git.8pit.net/scc.git

  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
 15static int
 16gettype(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
 72static int
 73sgettype(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
 94Symbol *
 95elfgetsym(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 = gettype(elf, ent, sym->name);
117	sym->stype = sgettype(ent);
118	sym->value = ent->value;
119	sym->size = ent->size;
120	sym->index = *idx = n;
121
122	return sym;
123}