FreeCalypso > hg > freecalypso-reveng
view leo-obj/tool/richsym.c @ 144:fd772de226cb
tiobjd: started implementing rich symbolic info parsing
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Mon, 28 Apr 2014 08:04:39 +0000 |
parents | |
children | 25d3ead621f8 |
line wrap: on
line source
/* * Code for working with the "rich" symbolic info * present in TI's GPF libraries */ #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include "intstruct.h" #include "coffconst.h" #include "globals.h" extern unsigned get_u16(), get_u32(); extern char *storage_class_to_string(); static int try_typedef_hack(struct_sym) struct internal_syment *struct_sym; { unsigned tpdef_cand; struct internal_syment *tpdef_sym; if (!struct_sym->aux) return(0); tpdef_cand = get_u32(struct_sym->aux + 12); if (tpdef_cand >= nsymtab) return(0); tpdef_sym = symtab[tpdef_cand]; if (!tpdef_sym) return(0); if (tpdef_sym->class != C_TPDEF) return(0); if (tpdef_sym->type != struct_sym->type) return(0); if (tpdef_sym->name[0] != '_') return(0); if (!tpdef_sym->aux) return(0); if (get_u32(tpdef_sym->aux) != struct_sym->number) return(0); struct_sym->struct_name = tpdef_sym->name + 1; return(1); } static void preen_strtag_sym(sym, kw, expect_type) struct internal_syment *sym; char *kw; { char *buf; int isund, len; isund = (sym->name[0] == '_'); len = strlen(kw) + 1 + strlen(sym->name) + 1; if (isund) len--; else len += 2; buf = malloc(len); if (!buf) { perror("malloc"); exit(1); } if (isund) sprintf(buf, "%s %s", kw, sym->name + 1); else sprintf(buf, "%s \"%s\"", kw, sym->name); sym->struct_name = buf; sym->struct_name_raw = buf; if (sym->type != expect_type) { fprintf(stderr, "warning: type/class mismatch on tag symbol #%u\n", sym->number); return; } if (isund) return; try_typedef_hack(sym); } richsym_initial_preen() { unsigned n; struct internal_syment *sym; for (n = 0; n < nsymtab; n++) { sym = symtab[n]; if (!sym) continue; switch (sym->class) { case C_STRTAG: preen_strtag_sym(sym, "struct", T_STRUCT); continue; case C_UNTAG: preen_strtag_sym(sym, "union", T_UNION); continue; case C_ENTAG: preen_strtag_sym(sym, "enum", T_ENUM); continue; } } } char * get_struct_type_name(idx, expect_class, is_typedef) unsigned idx; { struct internal_syment *sym; if (idx >= nsymtab) { inv_idx: fprintf(stderr, "error: ref to invalid syment #%u for struct tag\n", idx); exit(1); } sym = symtab[idx]; if (!sym) goto inv_idx; if (sym->class != expect_class) { fprintf(stderr, "error: ref to syment #%u for struct tag, class != %s\n", idx, storage_class_to_string(expect_class, 0)); exit(1); } if (is_typedef) return(sym->struct_name_raw); else return(sym->struct_name); } char * get_base_type_of_syment(sym, is_typedef) struct internal_syment *sym; { switch (sym->type & 0xF) { case T_VOID: return("void"); case T_CHAR: if (is_typedef) return("signed char"); else return("char"); case T_SHORT: return("short"); case T_INT: return("int"); case T_LONG: return("long"); case T_FLOAT: return("float"); case T_DOUBLE: return("double"); case T_STRUCT: return get_struct_type_name(get_u32(sym->aux), C_STRTAG, is_typedef); case T_UNION: return get_struct_type_name(get_u32(sym->aux), C_UNTAG, is_typedef); case T_ENUM: return get_struct_type_name(get_u32(sym->aux), C_ENTAG, is_typedef); case T_UCHAR: if (is_typedef) return("unsigned char"); else return("u_char"); case T_USHORT: if (is_typedef) return("unsigned short"); else return("u_short"); case T_UINT: return("unsigned"); case T_ULONG: if (is_typedef) return("unsigned long"); else return("u_long"); default: return("__unknown_base_type"); } }