summaryrefslogtreecommitdiff
path: root/misc
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2017-08-16 14:53:18 -0700
committerH. Peter Anvin <hpa@zytor.com>2017-08-16 15:00:38 -0700
commita771be85f4647dc9ed9bbdc2938cafeaabe7a80e (patch)
tree05fdb61f057a56e921669dad697e70ece862f7bf /misc
parentf283c8f5c26bf16a9c1ae9e58e41da68b654a1e5 (diff)
downloadnasm-a771be85f4647dc9ed9bbdc2938cafeaabe7a80e.tar.gz
outobj: emit file dependency information
Some OMF toolchain can make use of file dependency information embedded in the object files. As implemented here, we don't try to absolutize the filenames, as that prevents moving around trees and is OS-dependent. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'misc')
-rw-r--r--misc/omfdump.c290
1 files changed, 278 insertions, 12 deletions
diff --git a/misc/omfdump.c b/misc/omfdump.c
index 322971e9..b32ba582 100644
--- a/misc/omfdump.c
+++ b/misc/omfdump.c
@@ -13,6 +13,8 @@
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
+#include <stdbool.h>
+#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
@@ -64,22 +66,69 @@ static const char *record_types[256] =
typedef void (*dump_func)(uint8_t, const uint8_t *, size_t);
-static void hexdump_data(unsigned int offset, const uint8_t *data, size_t n)
+/* Ordered collection type */
+struct collection {
+ size_t n; /* Elements in collection (not including 0) */
+ size_t s; /* Elements allocated (not including 0) */
+ const void **p; /* Element pointers */
+};
+
+struct collection c_names, c_lsegs, c_groups, c_extsym;
+
+static void nomem(void)
+{
+ fprintf(stderr, "%s: memory allocation error\n", progname);
+ exit(1);
+}
+
+#define INIT_SIZE 64
+static void add_collection(struct collection *c, const void *p)
+{
+ if (c->n >= c->s) {
+ size_t cs = c->s ? (c->s << 1) : INIT_SIZE;
+ const void **cp = realloc(c->p, cs*sizeof(const void *));
+
+ if (!cp)
+ nomem();
+
+ c->p = cp;
+ c->s = cs;
+
+ memset(cp + c->n, 0, (cs - c->n)*sizeof(const void *));
+ }
+
+ c->p[++c->n] = p;
+}
+
+static const void *get_collection(struct collection *c, size_t index)
+{
+ if (index >= c->n)
+ return NULL;
+
+ return c->p[index];
+}
+
+static void hexdump_data(unsigned int offset, const uint8_t *data,
+ size_t n, size_t field)
{
unsigned int i, j;
for (i = 0; i < n; i += 16) {
- printf(" %04x: ", i+offset);
+ printf(" %04x: ", i+offset);
for (j = 0; j < 16; j++) {
- if (i+j < n)
- printf("%02x%c", data[i+j], (j == 7) ? '-' : ' ');
- else
- printf(" ");
+ char sep = (j == 7) ? '-' : ' ';
+ if (i+j < field)
+ printf("%02x%c", data[i+j], sep);
+ else if (i+j < n)
+ printf("xx%c", sep); /* Beyond end of... */
+ else
+ printf(" "); /* No separator */
}
printf(" : ");
for (j = 0; j < 16; j++) {
- if (i+j < n)
- putchar(isprint(data[i+j]) ? data[i+j] : '.');
+ if (i+j < n)
+ putchar((i+j >= field) ? 'x' :
+ isprint(data[i+j]) ? data[i+j] : '.');
}
putchar('\n');
}
@@ -88,7 +137,7 @@ static void hexdump_data(unsigned int offset, const uint8_t *data, size_t n)
static void dump_unknown(uint8_t type, const uint8_t *data, size_t n)
{
(void)type;
- hexdump_data(0, data, n);
+ hexdump_data(0, data, n, n);
}
static void dump_coment(uint8_t type, const uint8_t *data, size_t n)
@@ -116,31 +165,248 @@ static void dump_coment(uint8_t type, const uint8_t *data, size_t n)
[0xdc] = "Date",
[0xdd] = "Timestamp",
[0xdf] = "User",
+ [0xe3] = "Type definition",
+ [0xe8] = "Filename",
[0xe9] = "Dependency file",
[0xff] = "Command line"
};
if (n < 2) {
- dump_unknown(type, data, n);
+ hexdump_data(type, data, 2, n);
return;
}
type = data[0];
class = data[1];
- printf(" [NP=%d NL=%d UD=%02X] %02X %s\n",
+ printf(" [NP=%d NL=%d UD=%02X] %02X %s\n",
(type >> 7) & 1,
(type >> 6) & 1,
type & 0x3f,
class,
coment_class[class] ? coment_class[class] : "???");
- hexdump_data(2, data+2, n-2);
+ hexdump_data(2, data+2, n-2, n-2);
+}
+
+/* Parse an index field */
+static uint16_t get_index(const uint8_t **pp)
+{
+ uint8_t c;
+
+ c = *(*pp)++;
+ if (c & 0x80) {
+ return ((c & 0x7f) << 8) + *(*pp)++;
+ } else {
+ return c;
+ }
+}
+
+static uint16_t get_16(const uint8_t **pp)
+{
+ uint16_t v = *(const uint16_t *)(*pp);
+ (*pp) += 2;
+
+ return v;
+}
+
+static uint32_t get_32(const uint8_t **pp)
+{
+ const uint32_t v = *(const uint32_t *)(*pp);
+ (*pp) += 4;
+
+ return v;
+}
+
+/* Returns a name as a C string in a newly allocated buffer */
+char *lname(int index)
+{
+ char *s;
+ const char *p = get_collection(&c_names, index);
+ size_t len;
+
+ if (!p)
+ return NULL;
+
+ len = (uint8_t)p[0];
+
+ s = malloc(len+1);
+ if (!s)
+ nomem();
+
+ memcpy(s, p+1, len);
+ s[len] = '\0';
+
+ return s;
+}
+
+/* LNAMES or LLNAMES */
+static void dump_lnames(uint8_t type, const uint8_t *data, size_t n)
+{
+ const uint8_t *p = data;
+ const uint8_t *end = data + n;
+
+ while (p < end) {
+ size_t l = *p+1;
+ if (l > n) {
+ add_collection(&c_names, NULL);
+ printf(" # %4u 0x%04x: \"%.*s... <%zu missing bytes>\n",
+ c_names.n, c_names.n, n-1, p+1, l-n);
+ } else {
+ add_collection(&c_names, p);
+ printf(" # %4u 0x%04x: \"%.*s\"\n",
+ c_names.n, c_names.n, l-1, p+1);
+ }
+ hexdump_data(p-data, p, l, n);
+ p += l;
+ n -= l;
+ }
+}
+
+/* SEGDEF16 or SEGDEF32 */
+static void dump_segdef(uint8_t type, const uint8_t *data, size_t n)
+{
+ bool big = type & 1;
+ const uint8_t *p = data;
+ const uint8_t *end = data+n;
+ uint8_t attr;
+ static const char * const alignment[8] =
+ { "ABS", "BYTE", "WORD", "PARA", "PAGE", "DWORD", "LTL", "?ALIGN" };
+ static const char * const combine[8] =
+ { "PRIVATE", "?COMMON", "PUBLIC", "?COMBINE", "?PUBLIC", "STACK", "COMMON", "?PUBLIC" };
+ uint16_t idx;
+ char *s;
+
+ if (p >= end)
+ return;
+
+ attr = *p++;
+
+ printf(" # %s (A%u) %s (C%u) %s%s",
+ alignment[(attr >> 5) & 7], (attr >> 5) & 7,
+ combine[(attr >> 2) & 7], (attr >> 2) & 7,
+ (attr & 0x02) ? "MAXSIZE " : "",
+ (attr & 0x01) ? "USE32" : "USE16");
+
+ if (((attr >> 5) & 7) == 0) {
+ /* Absolute segment */
+ if (p+3 > end)
+ goto dump;
+ printf(" AT %04x:", get_16(&p));
+ printf("%02x", *p++);
+ }
+
+ if (big) {
+ if (p+4 > end)
+ goto dump;
+ printf(" size 0x%08x", get_32(&p));
+ } else {
+ if (p+2 > end)
+ goto dump;
+ printf(" size 0x%04x", get_16(&p));
+ }
+
+ idx = get_index(&p);
+ if (p > end)
+ goto dump;
+ s = lname(idx);
+ printf(" name '%s'", s);
+
+ idx = get_index(&p);
+ if (p > end)
+ goto dump;
+ s = lname(idx);
+ printf(" class '%s'", s);
+
+ idx = get_index(&p);
+ if (p > end)
+ goto dump;
+ s = lname(idx);
+ printf(" ovl '%s'", s);
+
+dump:
+ putchar('\n');
+ hexdump_data(0, data, n, n);
+}
+
+/* FIXUPP16 or FIXUPP32 */
+static void dump_fixupp(uint8_t type, const uint8_t *data, size_t n)
+{
+ bool big = type & 1;
+ const uint8_t *p = data;
+ const uint8_t *end = data + n;
+ static const char * const method_base[4] =
+ { "SEGDEF", "GRPDEF", "EXTDEF", "frame#" };
+
+ while (p < end) {
+ const uint8_t *start = p;
+ uint8_t op = *p++;
+ uint16_t index;
+ uint32_t disp;
+
+ if (!(op & 0x80)) {
+ /* THREAD record */
+ bool frame = !!(op & 0x40);
+
+ printf(" THREAD %-7s%d%s method %c%d (%s)",
+ frame ? "frame" : "target", op & 3,
+ (op & 0x20) ? " +flag5?" : "",
+ (op & 0x40) ? 'F' : 'T',
+ op & 3, method_base[op & 3]);
+
+ if ((op & 0x50) != 0x50) {
+ printf(" index 0x%04x", get_index(&p));
+ }
+ putchar('\n');
+ } else {
+ /* FIXUP subrecord */
+ uint8_t fix;
+
+ printf(" FIXUP %s-rel location %2d offset 0x%03x",
+ (op & 0x40) ? "seg" : "self",
+ (op & 0x3c) >> 2,
+ ((op & 3) << 8) + *p++);
+
+ fix = *p++;
+ printf("\n frame %s%d%s",
+ (fix & 0x80) ? "thread " : "F",
+ ((fix & 0x70) >> 4),
+ ((fix & 0xc0) == 0xc0) ? "?" : "");
+
+ if ((fix & 0xc0) == 0)
+ printf(" datum 0x%04x", get_index(&p));
+
+ printf("\n target %s%d",
+ (fix & 0x10) ? "thread " : "method T",
+ fix & 3);
+
+ if ((fix & 0x10) == 0)
+ printf(" (%s)", method_base[fix & 3]);
+
+ printf(" datum 0x%04x", get_index(&p));
+
+ if ((fix & 0x08) == 0) {
+ if (big) {
+ printf(" disp 0x%08x", get_32(&p));
+ } else {
+ printf(" disp 0x%04x", get_16(&p));
+ }
+ }
+ putchar('\n');
+ }
+ hexdump_data(start-data, start, p-start, n-(start-data));
+ }
}
static const dump_func dump_type[256] =
{
[0x88] = dump_coment,
+ [0x96] = dump_lnames,
+ [0x98] = dump_segdef,
+ [0x99] = dump_segdef,
+ [0x9c] = dump_fixupp,
+ [0x9d] = dump_fixupp,
+ [0xca] = dump_lnames,
};
int dump_omf(int fd)