diff 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 diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/leo-obj/tool/richsym.c	Mon Apr 28 08:04:39 2014 +0000
@@ -0,0 +1,184 @@
+/*
+ * 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");
+	}
+}