Re: [hatari-devel] Support for loading GNU-style symbols from a.out executables

[ Thread Index | Date Index | More lists.tuxfamily.org/hatari-devel Archives ]


On Mittwoch, 8. November 2017 01:08:41 CET Thorsten Otto wrote:
> I can do that if nobody else volunteers 

done know ;)

I also added the symbol support to the gst2ascii tool.

To activate the new screen-size dependent display support, you have to change 
the nDisasmLines and nMemdebugLines variables in already existing config files 
to -1, which is now also written as default. I choosed -1, because zero was 
already special-treated in the profiling commands. Maybe that should also be 
mentioned somewhere, at least in some changelog.

What i noticed when adding the symbol support to the tool: it looks like the 
gst symbols produced by gcc are always section-based, which means that all 
data & bss addresses start at zero again. I'm not sure wether that is 
intended, or a bug in the binutils, but although the tool tries to catch that 
case, it makes no attempt to change the value. That makes sorting the symbols 
by address rather useless, and would make it difficult for a user to find out the 
real address of a variable.

Also, the output from the a.out symbols (and also what is e.g. produced by the 
map2sym.sh script from EmuTOS) is different, ie. the addresses of the data 
segment are starting just after the text segment (for Emutos this is 
irrelevant anyway, since there is no data segment, and the bss segment is 
located in ram). I don't know wether that symbols are used at all by Hatari, 
at least for profiling they won't be needed, but if they are, one or the other 
of this functions should be changed to produce a consistent result.

# HG changeset patch
# User Thorsten Otto <admin@xxxxxxxxxxx>
# Date 1510120248 -3600
#      Wed Nov 08 06:50:48 2017 +0100
# Node ID 85c0a63b555c10f6fa15386afcfb1aff5fda096d
# Parent  5bb370731f22a5acdf43cde6cf09198847054cd7
Supprtort loading GNU-style symbols for gst2ascii tool

diff -r 5bb370731f22 -r 85c0a63b555c tools/debugger/gst2ascii.c
--- a/tools/debugger/gst2ascii.c	Tue Nov 07 00:49:50 2017 +0100
+++ b/tools/debugger/gst2ascii.c	Wed Nov 08 06:50:48 2017 +0100
@@ -25,6 +25,7 @@
 # include <SDL_endian.h>
 #endif
 #include <assert.h>
+#include "../../src/debug/a.out.h"
 
 typedef enum {
 	SYMTYPE_TEXT = 1,
@@ -44,6 +45,7 @@
 	int symbols;		/* initial symbol count */
 	symbol_t *addresses;	/* items sorted by address */
 	symbol_t *names;	/* items sorted by symbol name */
+	char *strtab;
 } symbol_list_t;
 
 typedef struct {
@@ -51,6 +53,9 @@
 	uint32_t end;
 } prg_section_t;
 
+/* Magic used to denote symbols in GNU-style (a.out) format */
+#define SYMBOL_FORMAT_GNU 0x474E555f
+
 /* ------------------ options & usage ------------------ */
 
 #ifdef WIN32
@@ -129,8 +134,6 @@
 	if (addr1 > addr2) {
 		return 1;
 	}
-	fprintf(stderr, "WARNING: symbols '%s' & '%s' have the same 0x%x address.\n",
-		((const symbol_t*)s1)->name, ((const symbol_t*)s2)->name, addr1);
 	return 0;
 }
 
@@ -144,11 +147,41 @@
 	int ret;
 
 	ret = strcmp(name1, name2);
-	if (!ret) {
-		fprintf(stderr, "WARNING: addresses 0x%x & 0x%x have the same '%s' name.\n",
-			((const symbol_t*)s1)->address, ((const symbol_t*)s2)->address, name1);
+	return ret;
+}
+
+/**
+ * check for duplicate addresses in symbol list
+ */
+static void symbols_check_addresses(const symbol_t *syms, int count)
+{
+	int i, j;
+
+	for (i = 0; i < (count - 1); i++)
+	{
+		for (j = i + 1; j < count && syms[i].address == syms[j].address; j++) {
+			fprintf(stderr, "WARNING: symbols '%s' & '%s' have the same 0x%x address.\n",
+				syms[i].name, syms[j].name, syms[i].address);
+			i = j;
+		}
 	}
-	return ret;
+}
+
+/**
+ * check for duplicate names in symbol list
+ */
+static void symbols_check_names(const symbol_t *syms, int count)
+{
+	int i, j;
+
+	for (i = 0; i < (count - 1); i++)
+	{
+		for (j = i + 1; j < count && strcmp(syms[i].name, syms[j].name) == 0; j++) {
+			fprintf(stderr, "WARNING: addresses 0x%x & 0x%x have the same '%s' name.\n",
+				syms[i].address, syms[j].address, syms[i].name);
+			i = j;
+		}
+	}
 }
 
 /**
@@ -360,6 +393,238 @@
 	return list;
 }
 
+
+/* Utility macro. Get a 16- or 32 bit value from a pointer to
+   unsigned char. */
+#define get16be(c) (((c)[0] << 8) | ((c)[1]))
+#define get32be(c) (((uint32_t)((c)[0]) << 24) | ((uint32_t)((c)[1]) << 16) | ((uint32_t)((c)[2]) << 8) | ((uint32_t)((c)[3])))
+
+/**
+ * Load symbols of given type and the symbol address addresses from
+ * a.out format symbol table, and add given offsets to the addresses:
+ * Return symbols list or NULL for failure.
+ */
+static symbol_list_t* symbols_load_gnu(FILE *fp, prg_section_t *sections, Uint32 tablesize, Uint32 stroff, Uint32 strsize)
+{
+	size_t slots = tablesize / SIZEOF_STRUCT_NLIST;
+	size_t i;
+	size_t strx;
+	unsigned char *p;
+	symbol_t *sym;
+	uint32_t nread;
+	symbol_list_t *list;
+	unsigned char n_type;
+	unsigned char n_other;
+	unsigned short n_desc;
+	int dtypes, locals, ofiles, count, outside, notypes;
+	size_t len;
+	static char invalid[] = "<invalid>";
+	static char empty[] = "";
+	prg_section_t *section;
+
+	if (!(list = symbol_list_alloc(slots))) {
+		return NULL;
+	}
+
+	list->strtab = (char *)malloc(tablesize + strsize);
+
+	if (list->strtab == NULL)
+	{
+		symbol_list_free(list);
+		return NULL;
+	}
+
+	nread = fread(list->strtab, tablesize + strsize, 1, fp);
+	if (nread != 1)
+	{
+		perror("ERROR: reading symbols failed");
+		symbol_list_free(list);
+		return NULL;
+	}
+
+	p = (unsigned char *)list->strtab;
+	sym = list->names;
+
+	outside = dtypes = ofiles = locals = count = notypes = 0;
+	for (i = 0; i < slots; i++)
+	{
+		strx = get32be(p);
+		p += 4;
+		n_type = *p++;
+		n_other = *p++;
+		n_desc = get16be(p);
+		p += 2;
+		sym->address = get32be(p);
+		p += 4;
+		if (strx)
+		{
+			if (strx >= strsize)
+			{
+				fprintf(stderr, "symbol name index %x out of range\n", (unsigned int)strx);
+				sym->name = invalid;
+			} else
+			{
+				sym->name = list->strtab + strx + stroff;
+			}
+		} else
+		{
+			sym->name = empty;
+		}
+		if (n_type & N_STAB)
+		{
+			dtypes++;
+			continue;
+		}
+		section = NULL;
+		switch (n_type & (N_TYPE|N_EXT))
+		{
+		case N_UNDF:
+		case N_UNDF|N_EXT:
+			/* shouldn't happen here */
+			locals++;
+			continue;
+		case N_ABS:
+		case N_ABS|N_EXT:
+			sym->type = SYMTYPE_ABS;
+			break;
+		case N_TEXT:
+			len = strlen(sym->name);
+			if (strchr(sym->name, '/') || (len > 2 && sym->name[len-2] == '.' && sym->name[len-1] == 'o')) {
+				ofiles++;
+				continue;
+			}
+			sym->type = SYMTYPE_TEXT;
+			section = &(sections[0]);
+			break;
+		case N_TEXT|N_EXT:
+			sym->type = SYMTYPE_TEXT;
+			section = &(sections[0]);
+			break;
+		case N_DATA:
+		case N_DATA|N_EXT:
+			sym->type = SYMTYPE_DATA;
+			section = &(sections[1]);
+			break;
+		case N_BSS:
+		case N_BSS|N_EXT:
+		case N_COMM:
+		case N_COMM|N_EXT:
+			sym->type = SYMTYPE_BSS;
+			section = &(sections[2]);
+			break;
+		case N_FN:
+			ofiles++;
+			continue;
+		case N_SIZE:
+		case N_WARNING:
+		case N_SETA:
+		case N_SETT:
+		case N_SETD:
+		case N_SETB:
+		case N_SETV:
+			dtypes++;
+			continue;
+		case N_WEAKU:
+		case N_WEAKT:
+		case N_WEAKD:
+		case N_WEAKB:
+			locals++;
+			continue;
+		default:
+			fprintf(stderr, "WARNING: ignoring symbol '%s' in slot %u of unknown type 0x%x.\n", sym->name, (unsigned int)i, n_type);
+			continue;
+		}
+		/*
+		 * the value of a common symbol is its size, not its address:
+		 */
+		if (((n_type & N_TYPE) == N_COMM) ||
+			(((n_type & N_EXT) && (n_type & N_TYPE) == N_UNDF && sym->address != 0)))
+		{
+			/* if we ever want to know a symbols size, get that here */
+			fprintf(stderr, "WARNING: ignoring common symbol '%s' in slot %u.\n", sym->name, (unsigned int)i);
+			continue;
+		}
+		if (Options.notypes & sym->type) {
+			notypes++;
+			continue;
+		}
+		if (Options.no_local) {
+			if (sym->name[0] == '.' && sym->name[1] == 'L') {
+				locals++;
+				continue;
+			}
+		}
+		if (Options.no_obj) {
+			const char *gcc_sym[] = {
+				"___gnu_compiled_c",
+				"gcc2_compiled."
+			};
+			int j, len = strlen(sym->name);
+			/* object / file name? */
+			if (len > 2 && ((sym->name[len-2] == '.' && sym->name[len-1] == 'o') || strchr(sym->name, '/'))) {
+				ofiles++;
+				continue;
+			}
+			/* useless symbols GCC (v2) seems to add to every object? */
+			for (j = 0; j < ARRAY_SIZE(gcc_sym); j++) {
+				if (strcmp(sym->name, gcc_sym[j]) == 0) {
+					ofiles++;
+					j = -1;
+					break;
+				}
+			}
+			if (j < 0) {
+				continue;
+			}
+		}
+		if (section) {
+			sym->address += sections[0].offset;
+			if (sym->address > (section->end + 1)) {
+				++outside;
+#if 0
+				/* VBCC has 1 symbol outside of its section */
+				if (outside > 2) {
+					/* potentially buggy version of VBCC vlink used */
+					fprintf(stderr, "ERROR: too many invalid offsets, skipping rest of symbols!\n");
+					symbol_list_free(list);
+					return NULL;
+				}
+#endif
+				fprintf(stderr, "WARNING: ignoring symbol '%s' of %c type in slot %u with invalid offset 0x%x (>= 0x%x).\n",
+					sym->name, symbol_char(sym->type), (unsigned int)i, sym->address, section->end);
+				continue;
+			}
+		}
+		sym++;
+		count++;
+		(void) n_desc;
+		(void) n_other;
+	}
+
+	if (notypes) {
+		fprintf(stderr, "NOTE: ignored %d unwanted symbol types.\n", notypes);
+	}
+	if (dtypes) {
+		fprintf(stderr, "NOTE: ignored %d debugging symbols.\n", dtypes);
+	}
+	if (locals) {
+		fprintf(stderr, "NOTE: ignored %d unnamed / local symbols (= name starts with '.L').\n", locals);
+	}
+	if (ofiles) {
+		/* object file path names most likely get truncated and
+		 * as result cause unnecessary symbol name conflicts in
+		 * addition to object file addresses conflicting with
+		 * first symbol in the object file.
+		 */
+		fprintf(stderr, "NOTE: ignored %d object symbols (= name has '/', ends in '.o' or is GCC internal).\n", ofiles);
+	}
+
+	list->symbols = slots;
+	list->count = count;
+	return list;
+}
+
+
 /**
  * Print program header information.
  * Return false for unrecognized symbol table type.
@@ -383,6 +648,9 @@
 	case 0x4D694E54:	/* "MiNT" */
 		info = "GCC/MiNT executable, GST symbol table";
 		break;
+	case SYMBOL_FORMAT_GNU:	/* "GNU_" */
+		info = "GCC/MiNT executable, a.out symbol table";
+		break;
 	case 0x0:
 		info = "TOS executable, DRI / GST symbol table";
 		break;
@@ -420,6 +688,9 @@
 	int offset, reads = 0;
 	Uint16 relocflag;
 	symbol_list_t* symbols;
+	Uint32 symoff = 0;
+	Uint32 stroff = 0;
+	Uint32 strsize = 0;
 
 	/* get TEXT, DATA & BSS section sizes */
 	reads += fread(&textlen, sizeof(textlen), 1, fp);
@@ -445,6 +716,76 @@
 		fprintf(stderr, "ERROR: program header reading failed!\n");
 		return NULL;
 	}
+	/*
+	 * check for GNU-style symbol table in aexec header
+	 */
+	if (tabletype == 0x4D694E54) { /* MiNT */
+		Uint32 magic1, magic2;
+		Uint32 dummy;
+		Uint32 a_text, a_data, a_bss, a_syms, a_entry, a_trsize, a_drsize;
+		Uint32 g_tparel_pos, g_tparel_size, g_stkpos, g_symbol_format;
+
+		reads  = fread(&magic1, sizeof(magic1), 1, fp);
+		magic1 = SDL_SwapBE32(magic1);
+		reads += fread(&magic2, sizeof(magic2), 1, fp);
+		magic2 = SDL_SwapBE32(magic2);
+		if (reads == 2 &&
+			((magic1 == 0x283a001a && magic2 == 0x4efb48fa) || 	/* Original binutils: move.l 28(pc),d4; jmp 0(pc,d4.l) */
+			 (magic1 == 0x203a001a && magic2 == 0x4efb08fa))) {	/* binutils >= 2.18-mint-20080209: move.l 28(pc),d0; jmp 0(pc,d0.l) */
+			reads += fread(&dummy, sizeof(dummy), 1, fp);	/* skip a_info */
+			reads += fread(&a_text, sizeof(a_text), 1, fp);
+			a_text = SDL_SwapBE32(a_text);
+			reads += fread(&a_data, sizeof(a_data), 1, fp);
+			a_data = SDL_SwapBE32(a_data);
+			reads += fread(&a_bss, sizeof(a_bss), 1, fp);
+			a_bss = SDL_SwapBE32(a_bss);
+			reads += fread(&a_syms, sizeof(a_syms), 1, fp);
+			a_syms = SDL_SwapBE32(a_syms);
+			reads += fread(&a_entry, sizeof(a_entry), 1, fp);
+			a_entry = SDL_SwapBE32(a_entry);
+			reads += fread(&a_trsize, sizeof(a_trsize), 1, fp);
+			a_trsize = SDL_SwapBE32(a_trsize);
+			reads += fread(&a_drsize, sizeof(a_drsize), 1, fp);
+			a_drsize = SDL_SwapBE32(a_drsize);
+			reads += fread(&g_tparel_pos, sizeof(g_tparel_pos), 1, fp);
+			g_tparel_pos = SDL_SwapBE32(g_tparel_pos);
+			reads += fread(&g_tparel_size, sizeof(g_tparel_size), 1, fp);
+			g_tparel_size = SDL_SwapBE32(g_tparel_size);
+			reads += fread(&g_stkpos, sizeof(g_stkpos), 1, fp);
+			g_stkpos = SDL_SwapBE32(g_stkpos);
+			reads += fread(&g_symbol_format, sizeof(g_symbol_format), 1, fp);
+			g_symbol_format = SDL_SwapBE32(g_symbol_format);
+			if (g_symbol_format == 0)
+			{
+				tabletype = SYMBOL_FORMAT_GNU;
+			}
+			if ((a_text + (256 - 28)) != textlen)
+				fprintf(stderr, "warning: insonsistent text segment size %08x != %08x\n", textlen, a_text + (256 - 28));
+			if (a_data != datalen)
+				fprintf(stderr, "warning: insonsistent data segment size %08x != %08x\n", datalen, a_data);
+			if (a_bss != bsslen)
+				fprintf(stderr, "warning: insonsistent bss segment size %08x != %08x\n", bsslen, a_bss);
+			/*
+			 * the symbol table size in the GEMDOS header includes the string table,
+			 * the symbol table size in the exec header does not.
+			 */
+			if (tabletype == SYMBOL_FORMAT_GNU)
+			{
+				strsize = tablesize - a_syms;
+				tablesize = a_syms;
+				stroff = a_syms;
+			}
+
+			textlen = a_text + (256 - 28);
+			datalen = a_data;
+			bsslen = a_bss;
+			symoff = 0x100 + /* sizeof(extended exec header) */
+				a_text +
+				a_data +
+				a_trsize +
+				a_drsize;
+		}
+	}
 	if (!symbols_print_prg_info(tabletype, prgflags, relocflag)) {
 		return NULL;
 	}
@@ -453,33 +794,52 @@
 		return NULL;
 	}
 
-	/* symbols already have suitable offsets, so only acceptable end position needs to be calculated */
-	sections[0].offset = 0;
-	sections[0].end = textlen;
-	sections[1].offset = 0;
-	sections[1].end = datalen;
-	sections[2].offset = 0;
-	sections[2].end = bsslen;
+	if (tabletype == SYMBOL_FORMAT_GNU) {
+		/* symbols already have suitable offsets, so only acceptable end position needs to be calculated */
+		sections[0].offset = 0;
+		sections[0].end = textlen;
+		sections[1].offset = textlen;
+		sections[1].end = textlen + datalen;
+		sections[2].offset = textlen + datalen;
+		sections[2].end = textlen + datalen + bsslen;
 
-	/* go to start of symbol table */
-	offset = 0x1C + textlen + datalen;
-	if (fseek(fp, offset, SEEK_SET) < 0) {
-		perror("ERROR: seeking to symbol table failed");
-		return NULL;
-	}
-	fprintf(stderr, "Trying to load symbol table at offset 0x%x...\n", offset);
-	symbols = symbols_load_dri(fp, sections, tablesize);
+		/* go to start of symbol table */
+		offset = symoff;
+		if (fseek(fp, offset, SEEK_SET) < 0) {
+			perror("ERROR: seeking to symbol table failed");
+			return NULL;
+		}
+		fprintf(stderr, "Trying to load symbol table at offset 0x%x...\n", offset);
+		symbols = symbols_load_gnu(fp, sections, tablesize, stroff, strsize);
+	} else {
+		/* symbols already have suitable offsets, so only acceptable end position needs to be calculated */
+		sections[0].offset = 0;
+		sections[0].end = textlen;
+		sections[1].offset = 0;
+		sections[1].end = datalen;
+		sections[2].offset = 0;
+		sections[2].end = bsslen;
 
-	if (symbols == INVALID_SYMBOL_OFFSETS && fseek(fp, offset, SEEK_SET) == 0) {
-		fprintf(stderr, "Re-trying with TEXT-relative BSS/DATA section offsets...\n");
-		sections[1].end += textlen;
-		sections[2].end += (textlen + datalen);
+		/* go to start of symbol table */
+		offset = 0x1C + textlen + datalen;
+		if (fseek(fp, offset, SEEK_SET) < 0) {
+			perror("ERROR: seeking to symbol table failed");
+			return NULL;
+		}
+		fprintf(stderr, "Trying to load symbol table at offset 0x%x...\n", offset);
 		symbols = symbols_load_dri(fp, sections, tablesize);
-		if (symbols) {
-			fprintf(stderr, "Load symbols without giving separate BSS/DATA offsets (they're TEXT relative).\n");
+
+		if (symbols == INVALID_SYMBOL_OFFSETS && fseek(fp, offset, SEEK_SET) == 0) {
+			fprintf(stderr, "Re-trying with TEXT-relative BSS/DATA section offsets...\n");
+			sections[1].end += textlen;
+			sections[2].end += (textlen + datalen);
+			symbols = symbols_load_dri(fp, sections, tablesize);
+			if (symbols) {
+				fprintf(stderr, "Load symbols without giving separate BSS/DATA offsets (they're TEXT relative).\n");
+			}
+		} else {
+			fprintf(stderr, "Load symbols with 'symbols <filename> TEXT DATA BSS' after starting the program.\n");
 		}
-	} else {
-		fprintf(stderr, "Load symbols with 'symbols <filename> TEXT DATA BSS' after starting the program.\n");
 	}
 	if (!symbols || symbols == INVALID_SYMBOL_OFFSETS) {
 		fprintf(stderr, "\n\n*** Try with 'nm -n <program>' (Atari/cross-compiler tool) instead ***\n\n");
@@ -534,6 +894,13 @@
 	/* sort both lists, with different criteria */
 	qsort(list->addresses, list->count, sizeof(symbol_t), symbols_by_address);
 	qsort(list->names, list->count, sizeof(symbol_t), symbols_by_name);
+
+	/* check for duplicate addresses */
+	symbols_check_addresses(list->addresses, list->count);
+
+	/* check for duplicate names */
+	symbols_check_names(list->names, list->count);
+
 	return list;
 }
 
# HG changeset patch
# User Thorsten Otto <admin@xxxxxxxxxxx>
# Date 1510133156 -3600
#      Wed Nov 08 10:25:56 2017 +0100
# Node ID d7b21a9cc6a2864ba3ca9eb801f827b7312df6a1
# Parent  85c0a63b555c10f6fa15386afcfb1aff5fda096d
Use terminal size to determine number of lines to display in
disasm, memdump and profiling commands

diff -r 85c0a63b555c -r d7b21a9cc6a2 src/configuration.c
--- a/src/configuration.c	Wed Nov 08 06:50:48 2017 +0100
+++ b/src/configuration.c	Wed Nov 08 10:25:56 2017 +0100
@@ -594,8 +594,8 @@
 
 	/* Set defaults for debugger */
 	ConfigureParams.Debugger.nNumberBase = 10;
-	ConfigureParams.Debugger.nDisasmLines = 8;
-	ConfigureParams.Debugger.nMemdumpLines = 8;
+	ConfigureParams.Debugger.nDisasmLines = -1; /* <0: use terminal size */
+	ConfigureParams.Debugger.nMemdumpLines = -1; /* <0: use terminal size */
 	/* external one has nicer output, but isn't as complete as UAE one */
 	ConfigureParams.Debugger.bDisasmUAE = false;
 	ConfigureParams.Debugger.nDisasmOptions = Disasm_GetOptions();
diff -r 85c0a63b555c -r d7b21a9cc6a2 src/debug/debugcpu.c
--- a/src/debug/debugcpu.c	Wed Nov 08 06:50:48 2017 +0100
+++ b/src/debug/debugcpu.c	Wed Nov 08 10:25:56 2017 +0100
@@ -191,6 +191,14 @@
 	{
 		disasm_upper = 0xFFFFFFFF;
 		max_insts = ConfigureParams.Debugger.nDisasmLines;
+		if (max_insts < 0)
+		{
+			int rows, cols;
+			DebugUI_GetScreenSize(&rows, &cols);
+			max_insts = rows - 1;
+			if (max_insts <= 0)
+				max_insts = 8;
+		}
 	}
 
 	/* output a range */
@@ -391,7 +399,16 @@
 
 	if (!memdump_upper)
 	{
-		memdump_upper = memdump_addr + MEMDUMP_COLS * ConfigureParams.Debugger.nMemdumpLines;
+		int lines = ConfigureParams.Debugger.nMemdumpLines;
+		if (lines < 0)
+		{
+			int rows, cols;
+			DebugUI_GetScreenSize(&rows, &cols);
+			lines = rows - 1;
+			if (lines <= 0)
+				lines = 8;
+		}
+		memdump_upper = memdump_addr + MEMDUMP_COLS * lines;
 	}
 
 	while (memdump_addr < memdump_upper)
diff -r 85c0a63b555c -r d7b21a9cc6a2 src/debug/debugdsp.c
--- a/src/debug/debugdsp.c	Wed Nov 08 06:50:48 2017 +0100
+++ b/src/debug/debugdsp.c	Wed Nov 08 10:25:56 2017 +0100
@@ -165,6 +165,14 @@
 	if (!dsp_disasm_upper)
 	{
 		int lines = ConfigureParams.Debugger.nDisasmLines;
+		if (lines < 0)
+		{
+			int rows, cols;
+			DebugUI_GetScreenSize(&rows, &cols);
+			lines = rows - 1;
+			if (lines <= 0)
+				lines = 8;
+		}
 		if ( dsp_disasm_addr < (0xFFFF - lines))
 			dsp_disasm_upper = dsp_disasm_addr + lines;
 		else
@@ -261,6 +269,14 @@
 	if (!dsp_memdump_upper)
 	{
 		int lines = ConfigureParams.Debugger.nMemdumpLines;
+		if (lines < 0)
+		{
+			int rows, cols;
+			DebugUI_GetScreenSize(&rows, &cols);
+			lines = rows - 1;
+			if (lines <= 0)
+				lines = 8;
+		}
 		if ( dsp_memdump_addr < (0xFFFF - lines))
 			dsp_memdump_upper = dsp_memdump_addr + lines;
 		else
diff -r 85c0a63b555c -r d7b21a9cc6a2 src/debug/profilecpu.c
--- a/src/debug/profilecpu.c	Wed Nov 08 06:50:48 2017 +0100
+++ b/src/debug/profilecpu.c	Wed Nov 08 10:25:56 2017 +0100
@@ -354,6 +354,13 @@
 	} else {
 		end = size;
 		show = ConfigureParams.Debugger.nDisasmLines;
+		if (show < 0) {
+			int rows, cols;
+			DebugUI_GetScreenSize(&rows, &cols);
+			show = rows - 1;
+			if (show <= 0)
+				show = 0;
+		}
 		if (!show || show > active) {
 			show = active;
 		}
diff -r 85c0a63b555c -r d7b21a9cc6a2 src/debug/profiledsp.c
--- a/src/debug/profiledsp.c	Wed Nov 08 06:50:48 2017 +0100
+++ b/src/debug/profiledsp.c	Wed Nov 08 10:25:56 2017 +0100
@@ -139,6 +139,13 @@
 		show = active;
 	} else {
 		show = ConfigureParams.Debugger.nDisasmLines;
+		if (show < 0) {
+			int rows, cols;
+			DebugUI_GetScreenSize(&rows, &cols);
+			show = rows - 1;
+			if (show <= 0)
+				show = 0;
+		}
 		if (!show || show > active) {
 			show = active;
 		}


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/