1 | /* |
---|
2 | * Copyright (c) 1992-1998 Michael A. Cooper. |
---|
3 | * This software may be freely used and distributed provided it is not |
---|
4 | * sold for profit or used in part or in whole for commercial gain |
---|
5 | * without prior written agreement, and the author is credited |
---|
6 | * appropriately. |
---|
7 | */ |
---|
8 | |
---|
9 | /* |
---|
10 | * Frontend functions for kvm_*() functions |
---|
11 | * |
---|
12 | * It is assumed we HAVE_NLIST if we HAVE_KVM. |
---|
13 | */ |
---|
14 | |
---|
15 | #include <stdio.h> |
---|
16 | #include "defs.h" |
---|
17 | |
---|
18 | #if defined(HAVE_KVM) |
---|
19 | |
---|
20 | #include "defs.h" |
---|
21 | #include <fcntl.h> |
---|
22 | |
---|
23 | /* |
---|
24 | * Perform a kvm_close(). Really just here to be compatible. |
---|
25 | */ |
---|
26 | extern void KVMclose(kd) |
---|
27 | kvm_t *kd; |
---|
28 | { |
---|
29 | if (kd) |
---|
30 | (void) kvm_close(kd); |
---|
31 | } |
---|
32 | |
---|
33 | /* |
---|
34 | * Perform a kvm_open(). |
---|
35 | */ |
---|
36 | extern kvm_t *KVMopen() |
---|
37 | { |
---|
38 | kvm_t *kd = NULL; |
---|
39 | extern char *ProgramName; |
---|
40 | |
---|
41 | if ((kd = kvm_open((char *)NULL, (char *)NULL, (char *)NULL, O_RDONLY, |
---|
42 | ProgramName)) == NULL) { |
---|
43 | SImsg(SIM_GERR, "kvm_open failed: %s.", SYSERR); |
---|
44 | return((kvm_t *) NULL); |
---|
45 | } |
---|
46 | |
---|
47 | return(kd); |
---|
48 | } |
---|
49 | |
---|
50 | #if defined(HAVE_NLIST) || defined(HAVE_KNLIST) |
---|
51 | |
---|
52 | static nlist_t NListTab[] = { |
---|
53 | { 0 }, |
---|
54 | { 0 }, |
---|
55 | }; |
---|
56 | |
---|
57 | /* |
---|
58 | * Perform an nlist on "kd" looking for "Symbol" or "NameList". |
---|
59 | * Return the a pointer to the found nlist structure. |
---|
60 | * On failure, return NULL and KVMclos(kd). |
---|
61 | */ |
---|
62 | extern nlist_t *KVMnlist(kd, Symbol, NameList, NumNameList) |
---|
63 | kvm_t *kd; |
---|
64 | char *Symbol; |
---|
65 | nlist_t *NameList; |
---|
66 | int NumNameList; |
---|
67 | /*ARGSUSED*/ |
---|
68 | { |
---|
69 | nlist_t *NLPtr; |
---|
70 | nlist_t *TabPtr; |
---|
71 | char *cp; |
---|
72 | int Status; |
---|
73 | int NumEle; |
---|
74 | |
---|
75 | if (NameList) { |
---|
76 | NLPtr = NameList; |
---|
77 | TabPtr = NameList; |
---|
78 | NumEle = NumNameList; |
---|
79 | } else { |
---|
80 | TabPtr = NListTab; |
---|
81 | NLPtr = &NListTab[0]; |
---|
82 | NumEle = 1; |
---|
83 | memset((void *) NLPtr, 0, sizeof(nlist_t)); |
---|
84 | GetNlNamePtr(NLPtr) = Symbol; |
---|
85 | } |
---|
86 | |
---|
87 | #if defined(COFF) || defined(ELF) |
---|
88 | for (NLPtr = TabPtr; GetNlNamePtr(NLPtr); ++NLPtr) { |
---|
89 | cp = GetNlNamePtr(NLPtr); |
---|
90 | /* |
---|
91 | * Skip over initial '_' |
---|
92 | */ |
---|
93 | if (*cp == '_') |
---|
94 | GetNlNamePtr(NLPtr) = cp + 1; |
---|
95 | } |
---|
96 | #endif |
---|
97 | |
---|
98 | #if defined(HAVE_KNLIST) |
---|
99 | Status = knlist(TabPtr, NumEle, sizeof(nlist_t)); |
---|
100 | #else /* !HAVE_KNLIST */ |
---|
101 | Status = kvm_nlist(kd, TabPtr); |
---|
102 | #endif /* HAVE_KNLIST */ |
---|
103 | if (Status == -1) { |
---|
104 | cp = GetNlNamePtr(NLPtr); |
---|
105 | SImsg(SIM_GERR, "kvm_nlist name \"%s\" failed (status = %d): %s.", |
---|
106 | (cp) ? cp : "(unknown)", Status, SYSERR); |
---|
107 | KVMclose(kd); |
---|
108 | return((nlist_t *) NULL); |
---|
109 | } |
---|
110 | |
---|
111 | return(&TabPtr[0]); |
---|
112 | } |
---|
113 | #endif /* HAVE_NLIST || HAVE_KNLIST */ |
---|
114 | |
---|
115 | /* |
---|
116 | * Perform a kvm_read(). |
---|
117 | * |
---|
118 | * If DataType==KDT_STRING, read 1 byte at a time until '\0' or |
---|
119 | * NumBytes is reached. This is necessary in order to avoid |
---|
120 | * reading invalid memory pages from the kernel which can lead |
---|
121 | * to system crashes. |
---|
122 | * |
---|
123 | * If DataType==KDT_DATA then we read NumBytes of data into |
---|
124 | * Buf all at once. |
---|
125 | */ |
---|
126 | extern int KVMget(kd, Addr, Buf, NumBytes, DataType) |
---|
127 | kvm_t *kd; |
---|
128 | KVMaddr_t Addr; |
---|
129 | void *Buf; |
---|
130 | size_t NumBytes; |
---|
131 | int DataType; |
---|
132 | { |
---|
133 | char *Ptr; |
---|
134 | char *End; |
---|
135 | |
---|
136 | if (!kd) |
---|
137 | return(-1); |
---|
138 | |
---|
139 | switch (DataType) { |
---|
140 | case KDT_STRING: |
---|
141 | Ptr = (char *) Buf; |
---|
142 | End = (char *) &Ptr[NumBytes-1]; |
---|
143 | do { |
---|
144 | if (kvm_read(kd, Addr++, Ptr, 1) != 1) { |
---|
145 | SImsg(SIM_GERR, "kvm_read failed prematurely: %s.", SYSERR); |
---|
146 | return(-1); |
---|
147 | } |
---|
148 | } while (Ptr < End && *Ptr++); |
---|
149 | *Ptr = C_NULL; |
---|
150 | break; |
---|
151 | |
---|
152 | case KDT_DATA: |
---|
153 | if (kvm_read(kd, Addr, Buf, NumBytes) != NumBytes) { |
---|
154 | SImsg(SIM_GERR, "kvm_read failed (amount=%d): %s.", |
---|
155 | NumBytes, SYSERR); |
---|
156 | return(-1); |
---|
157 | } |
---|
158 | break; |
---|
159 | |
---|
160 | default: |
---|
161 | SImsg(SIM_UNKN, "Unknown Kernel Data Type: %d.", DataType); |
---|
162 | return(-1); |
---|
163 | } |
---|
164 | |
---|
165 | return(0); |
---|
166 | } |
---|
167 | |
---|
168 | /* |
---|
169 | * Check to see if PtrNL is valid. |
---|
170 | */ |
---|
171 | extern int _CheckNlist(PtrNL) |
---|
172 | nlist_t *PtrNL; |
---|
173 | { |
---|
174 | char *cp; |
---|
175 | |
---|
176 | if (!PtrNL) |
---|
177 | return(-1); |
---|
178 | |
---|
179 | /* |
---|
180 | * Should use n_type, but that's not set |
---|
181 | * correctly on some OS's. |
---|
182 | */ |
---|
183 | if (!PtrNL->n_value) { |
---|
184 | cp = GetNlNamePtr(PtrNL); |
---|
185 | SImsg(SIM_DBG, "Kernel symbol \"%s\" not found.", |
---|
186 | (cp) ? cp : "(unknown)"); |
---|
187 | return(-1); |
---|
188 | } |
---|
189 | |
---|
190 | return(0); |
---|
191 | } |
---|
192 | |
---|
193 | #endif /* HAVE_KVM */ |
---|