summaryrefslogtreecommitdiffstats
path: root/main/common/symtbl.c
blob: efc08c4c919fe271905a72e8f6c4b705bad02084 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/**************************************************************************
 *
 * Copyright (c) 2013 Alcatel-Lucent
 * 
 * Alcatel Lucent licenses this file to You under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License.  A copy of the License is contained the
 * file LICENSE at the top level of this repository.
 * You may also obtain a copy of the License at:
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 **************************************************************************
 *
 * symtbl.c:
 *
 * This file contains functions related to the symbol table option in
 * the monitor.
 *
 * Original author:     Ed Sutter (ed.sutter@alcatel-lucent.com)
 *
 */
#include "config.h"
#include "stddefs.h"
#include "genlib.h"
#if INCLUDE_TFSSYMTBL
#include <ctype.h>
#include "tfs.h"
#include "tfsprivate.h"

#ifndef SYMFILE
#define SYMFILE "symtbl"
#endif

/* SymFileFd():
 * Attempt to open the symbol table file.  First look to the SYMFILE env var;
 * else default to SYMFILE definition.  If the file exists, open it and return
 * the file descriptor; else return TFSERR_NOFILE.
 */
int
SymFileFd(int verbose)
{
	TFILE	*tfp;
	int		tfd;
	char	*symfile;

	/* Load symbol table file name.  If SYMFILE is not a variable, default
	 * to the string defined by SYMFILE.
	 */
	symfile = getenv("SYMFILE");
	if (!symfile)
		symfile = SYMFILE;

	tfp = tfsstat(symfile);
	if (!tfp) 
		return(TFSERR_NOFILE);

	tfd = tfsopen(symfile,TFS_RDONLY,0);
	if (tfd < 0) {
		if (verbose)
			printf("%s: %s\n",symfile,(char *)tfsctrl(TFS_ERRMSG,tfd,0));
		return(TFSERR_NOFILE);
	}
	return(tfd);
}

/* AddrToSym():
 *	Assumes each line of symfile is formatted as...
 *		synmame SP hex_address
 *	and that the symbols are sorted from lowest to highest address.
 *	Using the file specified by the incoming TFS file descriptor, 
 *	determine what symbol's address range covers the incoming address.
 *	If found, store the name of the symbol as well as the offset between
 *	the address of the symbol and the incoming address.
 *	Note, if the incoming file descriptor is -1, then we open (and later
 *	close) the file	here.
 *
 *	Return 1 if a match is found, else 0.
 */
int
AddrToSym(int tfdin,ulong addr,char *name,ulong *offset)
{
	int		lno, tfd;
	char	*space;
	ulong	thisaddr, lastaddr;
	char	thisline[84];
	char	lastline[sizeof(thisline)];

	lno = 1;
	if (offset)
		*offset = 0;
	lastaddr = 0;
	if (tfdin == -1) {
		tfd = SymFileFd(0);
		if (tfd == TFSERR_NOFILE)
			return(0);
	}
	else
		tfd = tfdin;
	tfsseek(tfd,0,TFS_BEGIN);
	while(tfsgetline(tfd,thisline,sizeof(thisline)-1)) {
		space = strpbrk(thisline,"\t ");
		if (!space)
			continue;
		*space++ = 0;
		while(isspace(*space))
			space++;
	
		thisaddr = strtoul(space,0,0);	/* Compute address from entry in	*/
										/* symfile. 						*/

		if (thisaddr == addr) {			/* Exact match, use this entry		*/
			strcpy(name,thisline);		/* in symfile.						*/
			if (tfdin == -1)
				tfsclose(tfd,0);
			return(1);
		}
		else if (thisaddr > addr) {		/* Address in symfile is greater	*/	
			if (lno == 1)				/* than incoming address...			*/
				break;					/* If this is first line of symfile */
			strcpy(name,lastline);		/* then return error.				*/
			if (offset)
				*offset = addr-lastaddr;/* Otherwise return the symfile		*/
			if (tfdin == -1)
				tfsclose(tfd,0);
			return(1);					/* entry previous to this one.		*/
		}
		else {							/* Address in symfile is less than	*/
			lastaddr = thisaddr;		/* incoming address, so just keep	*/
			strcpy(lastline,thisline);	/* a copy of this line and go to 	*/
			lno++;						/* the next.						*/
		}
	}
	if (tfdin == -1)
		tfsclose(tfd,0);
	sprintf(name,"0x%lx",addr);
	return(0);
}

/* getsym():
 * Provides a similar capability to shell variables on the command line
 * except that here, the variable replacement is based on the content of
 * a symbol file.  The file would be be loaded into TFS to provide
 * a potentially large number of symbols.
 * Looks for the file SYMFILE.  If non-existent, just return NULL.
 * If file exists, then search through the file for the incoming
 * symbol name and, if found, return the replacement for the symbol.
 * else return NULL.
 * The text file is formatted such that no line is greater than 40 characters.
 * Each line has 2 whitespace delimited strings.  The first string is
 * the symbol name and the second string is the replacement value for that
 * symbol.  The first string is assumed to start at the beginning of the
 * line, and the second string is separated from the first string by
 * spaces and/or tabs.
 * For example, here are a few lines:
 *
 *	   main		0x10400
 *	   func		0x10440
 *
 * With the above lines in SYMFILE, if %main were on the command line, it
 * would be replaced with 0x10400.
 */
char *
getsym(char *symname,char *line,int sizeofline)
{
	int		tfd;
	char	*space;

	if ((tfd = SymFileFd(1)) < 0) {
		return((char *)0);
	}

	while(tfsgetline(tfd,line,sizeofline)) {
		char *eol;
		eol = strpbrk(line,"\r\n");
		if (eol)
			*eol = 0;
		space = strpbrk(line,"\t ");
		if (!space)
			continue;
		*space = 0;
		if (!strcmp(line,symname)) {
			tfsclose(tfd,0);
			space++;
			while((*space == ' ') || (*space == '\t'))
				space++;
			return(space);
		}
	}
	tfsclose(tfd,0);
	return((char *)0);
}

#else

char *
getsym(char *symname,char *line,int sizeofline)
{
	return((char *)0);
}

int
AddrToSym(int tfd,ulong addr,char *name,ulong *offset)
{
	sprintf(name,"0x%lx",addr);
	return(0);
}

#endif