Skip to content

Commit b3be954

Browse files
author
Dave Anderson
committed
If a symbol or symbol+offset argument is passed to the "dis" command,
and there are multiple text symbols with the same symbol name, then display a message indicating that there are "duplicate text symbols found", followed by a list of the symbols. Without the patch, the duplicate symbol with the lowest virtual address is used. ([email protected], [email protected])
1 parent 21874fe commit b3be954

File tree

1 file changed

+114
-7
lines changed

1 file changed

+114
-7
lines changed

kernel.c

Lines changed: 114 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,8 +1306,103 @@ verify_namelist()
13061306
program_usage(SHORT_FORM);
13071307
}
13081308

1309+
/*
1310+
* From either a syment pointer, or a virtual address evaluated
1311+
* from a symbol name plus an offset value, determine whether
1312+
* there are multiple symbols with the same name.
1313+
1314+
* If there are multiple text symbols with the same name, then
1315+
* display a "duplicate text symbols found" message followed by
1316+
* a list of each symbol's information, and return FALSE.
1317+
*
1318+
* If there is one text symbol and one or more data symbols with
1319+
* the same name, reset the incoming address based upon the
1320+
* single text symbol, and return TRUE.
1321+
*
1322+
* All of the remaining possibilities return TRUE without changing
1323+
* the incoming address:
1324+
*
1325+
* (1) if an evaluated address cannot be resolved to any symbol.
1326+
* (2) if an evaluated address argument did not contain a symbol name.
1327+
* (3) if there is only one possible symbol resolution.
1328+
* (4) if there are multiple data symbols.
1329+
*/
1330+
static int
1331+
resolve_text_symbol(char *arg, struct syment *sp_in, struct gnu_request *req, int radix)
1332+
{
1333+
int text_symbols;
1334+
struct syment *sp, *sp_orig, *first_text_sp;
1335+
ulong offset, radix_flag;
1336+
1337+
if (sp_in) {
1338+
sp_orig = sp_in;
1339+
offset = 0;
1340+
} else if ((sp_orig = value_search(req->addr, &offset))) {
1341+
if (!strstr(arg, sp_orig->name))
1342+
return TRUE;
1343+
} else {
1344+
if (CRASHDEBUG(1))
1345+
error(INFO, "%s: no text symbol found\n", arg);
1346+
return TRUE;
1347+
}
1348+
1349+
if (symbol_name_count(sp_orig->name) <= 1)
1350+
return TRUE;
1351+
1352+
text_symbols = 0;
1353+
first_text_sp = NULL;
1354+
sp = sp_orig;
1355+
1356+
do {
1357+
if (is_symbol_text(sp)) {
1358+
if (!first_text_sp)
1359+
first_text_sp = sp;
1360+
text_symbols++;
1361+
}
1362+
} while ((sp = symbol_search_next(sp->name, sp)));
1363+
1364+
/*
1365+
* If no text symbols for a symbol name exist, let it be...
1366+
*/
1367+
if (!text_symbols) {
1368+
if (CRASHDEBUG(1))
1369+
error(INFO, "%s: no text symbol found\n", arg);
1370+
return TRUE;
1371+
}
13091372

1373+
/*
1374+
* If only one symbol with the specified name is text,
1375+
* reset the req->addr as appropriate in case a
1376+
* lower-value data symbol was originally selected.
1377+
*/
1378+
if (text_symbols == 1) {
1379+
if (sp_in)
1380+
req->addr = first_text_sp->value;
1381+
else
1382+
req->addr = first_text_sp->value + offset;
1383+
return TRUE;
1384+
}
13101385

1386+
/*
1387+
* Multiple text symbols with the same name exist.
1388+
* Display them all and return FALSE.
1389+
*/
1390+
error(INFO, "%s: duplicate text symbols found:\n", arg);
1391+
1392+
radix_flag = radix == 10 ? SHOW_DEC_OFFS : SHOW_HEX_OFFS;
1393+
sp = sp_orig;
1394+
1395+
do {
1396+
if (is_symbol_text(sp)) {
1397+
if (module_symbol(sp->value, NULL, NULL, NULL, 0))
1398+
show_symbol(sp, offset, SHOW_LINENUM|SHOW_MODULE|radix_flag);
1399+
else
1400+
show_symbol(sp, offset, SHOW_LINENUM|radix_flag);
1401+
}
1402+
} while ((sp = symbol_search_next(sp->name, sp)));
1403+
1404+
return FALSE;
1405+
}
13111406

13121407
/*
13131408
* This routine disassembles text in one of four manners. A starting
@@ -1363,7 +1458,7 @@ cmd_dis(void)
13631458
unfiltered = user_mode = do_machdep_filter = do_load_module_filter = 0;
13641459
radix = 0;
13651460

1366-
req = (struct gnu_request *)getbuf(sizeof(struct gnu_request));
1461+
req = (struct gnu_request *)GETBUF(sizeof(struct gnu_request));
13671462
req->buf = GETBUF(BUFSIZE);
13681463
req->flags |= GNU_FROM_TTY_OFF|GNU_RETURN_ON_ERROR;
13691464
req->count = 1;
@@ -1425,22 +1520,34 @@ cmd_dis(void)
14251520
radix = pc->output_radix;
14261521

14271522
if (args[optind]) {
1428-
if (can_eval(args[optind]))
1523+
if (can_eval(args[optind])) {
14291524
req->addr = eval(args[optind], FAULT_ON_ERROR, NULL);
1430-
else if (hexadecimal(args[optind], 0)) {
1525+
if (!user_mode &&
1526+
!resolve_text_symbol(args[optind], NULL, req, radix)) {
1527+
FREEBUF(req->buf);
1528+
FREEBUF(req);
1529+
return;
1530+
}
1531+
} else if (hexadecimal(args[optind], 0)) {
14311532
req->addr = htol(args[optind], FAULT_ON_ERROR, NULL);
1432-
if (!user_mode &&
1433-
!(sp = value_search(req->addr, &offset))) {
1533+
sp = value_search(req->addr, &offset);
1534+
if (!user_mode && !sp) {
14341535
error(WARNING,
14351536
"%lx: no associated kernel symbol found\n",
14361537
req->addr);
14371538
unfiltered = TRUE;
14381539
}
1439-
if (!offset)
1540+
if (!offset && sp && is_symbol_text(sp))
14401541
req->flags |= GNU_FUNCTION_ONLY;
14411542
} else if ((sp = symbol_search(args[optind]))) {
14421543
req->addr = sp->value;
1443-
req->flags |= GNU_FUNCTION_ONLY;
1544+
if (!resolve_text_symbol(args[optind], sp, req, radix)) {
1545+
FREEBUF(req->buf);
1546+
FREEBUF(req);
1547+
return;
1548+
}
1549+
if (is_symbol_text(sp))
1550+
req->flags |= GNU_FUNCTION_ONLY;
14441551
} else {
14451552
fprintf(fp, "symbol not found: %s\n", args[optind]);
14461553
fprintf(fp, "possible alternatives:\n");

0 commit comments

Comments
 (0)