1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /* Copyright (c) 1988 AT&T */
27 /* Copyright (c) 1989 AT&T */
28 /* All Rights Reserved */
29
30
31 /* UNIX HEADER */
32 #include <stdio.h>
33
34 /* SIZE HEADERS */
35 #include "defs.h"
36
37 /* ELF HEADERS */
38 #include "gelf.h"
39
40
41 /* SIZE FUNCTIONS CALLED */
42 extern void error();
43
44
45 /* FORMAT STRINGS */
46
47 static const char *prusect[3] = {
48 "%llx",
49 "%llo",
50 "%lld"
51 };
52
53 static const char *prusum[3] = {
54 " = 0x%llx\n",
55 " = 0%llo\n",
56 " = %lld\n"
57 };
58
59 static const char *format[3] = {
60 "%llx + %llx + %llx = 0x%llx\n",
61 "%llo + %llo + %llo = 0%llo\n",
62 "%lld + %lld + %lld = %lld\n"
63 };
64
65 static void process_phdr(Elf *elf, GElf_Half num);
66
67 void
process(Elf * elf)68 process(Elf * elf)
69 {
70 /* EXTERNAL VARIABLES USED */
71 extern int fflag; /* full format for sections */
72 extern int Fflag; /* full format for segments */
73 extern int nflag; /* include non-loadable segments or sections */
74 extern int numbase; /* hex, octal, or decimal */
75 extern char *fname;
76 extern char *archive;
77 extern int is_archive;
78 extern int oneflag;
79
80 /* LOCAL VARIABLES */
81 GElf_Xword size; /* total size in non-default case for sections */
82 /*
83 * size of first, second, third number and total size
84 * in default case for sections.
85 */
86 GElf_Xword first;
87 GElf_Xword second;
88 GElf_Xword third;
89 GElf_Xword totsize;
90 GElf_Ehdr ehdr;
91 GElf_Shdr shdr;
92 Elf_Scn *scn;
93 size_t ndx = 0, shnum = 0;
94 int numsect = 0;
95 int notfirst = 0;
96 int i;
97 char *name = 0;
98
99
100 /*
101 * If there is a program header and the -f flag requesting section infor-
102 * mation is not set, then process segments with the process_phdr function.
103 * Otherwise, process sections. For the default case, the first number
104 * shall be the size of all sections that are allocatable, nonwritable and
105 * not of type NOBITS; the second number shall be the size of all sections
106 * that are allocatable, writable, and not of type NOBITS; the third number
107 * is the size of all sections that are writable and not of type NOBITS.
108 * If -f is set, print the size of each allocatable section, followed by
109 * the section name in parentheses.
110 * If -n is set, print the size of all sections, followed by the section
111 * name in parentheses.
112 */
113
114 if (gelf_getehdr(elf, &ehdr) == 0) {
115 error(fname, "invalid file type");
116 return;
117 }
118 if ((ehdr.e_phnum != 0) && !(fflag)) {
119 process_phdr(elf, ehdr.e_phnum);
120 return;
121 }
122
123 if (is_archive) {
124 (void) printf("%s[%s]: ", archive, fname);
125 } else if (!oneflag && !is_archive) {
126 (void) printf("%s: ", fname);
127 }
128 if (elf_getshdrstrndx(elf, &ndx) == -1)
129 error(fname, "no string table");
130 scn = 0;
131 size = 0;
132 first = second = third = totsize = 0;
133
134 if (elf_getshdrnum(elf, &shnum) == -1)
135 error(fname, "can't get number of sections");
136
137 if (shnum == 0)
138 error(fname, "no section data");
139
140 numsect = shnum;
141 for (i = 0; i < numsect; i++) {
142 if ((scn = elf_nextscn(elf, scn)) == 0) {
143 break;
144 }
145 if (gelf_getshdr(scn, &shdr) == 0) {
146 error(fname, "could not get section header");
147 break;
148 }
149 if ((Fflag) && !(fflag)) {
150 error(fname, "no segment data");
151 return;
152 } else if ((!(shdr.sh_flags & SHF_ALLOC)) &&
153 fflag && !(nflag)) {
154 continue;
155 } else if ((!(shdr.sh_flags & SHF_ALLOC)) && !(nflag)) {
156 continue;
157 } else if ((shdr.sh_flags & SHF_ALLOC) &&
158 (!(shdr.sh_flags & SHF_WRITE)) &&
159 (!(shdr.sh_type == SHT_NOBITS)) &&
160 !(fflag) && !(nflag)) {
161 first += shdr.sh_size;
162 } else if ((shdr.sh_flags & SHF_ALLOC) &&
163 (shdr.sh_flags & SHF_WRITE) &&
164 (!(shdr.sh_type == SHT_NOBITS)) &&
165 !(fflag) && !(nflag)) {
166 second += shdr.sh_size;
167 } else if ((shdr.sh_flags & SHF_WRITE) &&
168 (shdr.sh_type == SHT_NOBITS) &&
169 !(fflag) && !(nflag)) {
170 third += shdr.sh_size;
171 }
172 name = elf_strptr(elf, ndx, (size_t)shdr.sh_name);
173
174 if (fflag || nflag) {
175 size += shdr.sh_size;
176 if (notfirst) {
177 (void) printf(" + ");
178 }
179 (void) printf(prusect[numbase], shdr.sh_size);
180 (void) printf("(%s)", name);
181 }
182 notfirst++;
183 }
184 if ((fflag || nflag) && (numsect > 0)) {
185 (void) printf(prusum[numbase], size);
186 }
187
188 if (!fflag && !nflag) {
189 totsize = first + second + third;
190 (void) printf(format[numbase],
191 first, second, third, totsize);
192 }
193
194 if (Fflag) {
195 if (ehdr.e_phnum != 0) {
196 process_phdr(elf, ehdr.e_phnum);
197 return;
198 } else {
199 error(fname, "no segment data");
200 return;
201 }
202 }
203 }
204
205 /*
206 * If there is a program exection header, process segments. In the default
207 * case, the first number is the file size of all nonwritable segments
208 * of type PT_LOAD; the second number is the file size of all writable
209 * segments whose type is PT_LOAD; the third number is the memory size
210 * minus the file size of all writable segments of type PT_LOAD.
211 * If the -F flag is set, size will print the memory size of each loadable
212 * segment, followed by its permission flags.
213 * If -n is set, size will print the memory size of all loadable segments
214 * and the file size of all non-loadable segments, followed by their
215 * permission flags.
216 */
217
218 static void
process_phdr(Elf * elf,GElf_Half num)219 process_phdr(Elf * elf, GElf_Half num)
220 {
221 int i;
222 int notfirst = 0;
223 GElf_Phdr p;
224 GElf_Xword memsize;
225 GElf_Xword total;
226 GElf_Xword First;
227 GElf_Xword Second;
228 GElf_Xword Third;
229 GElf_Xword Totsize;
230 extern int Fflag;
231 extern int nflag;
232 extern int numbase;
233 extern char *fname;
234 extern char *archive;
235 extern int is_archive;
236 extern int oneflag;
237
238 memsize = total = 0;
239 First = Second = Third = Totsize = 0;
240
241 if (is_archive) {
242 (void) printf("%s[%s]: ", archive, fname);
243 } else if (!oneflag && !is_archive) {
244 (void) printf("%s: ", fname);
245 }
246
247 for (i = 0; i < (int)num; i++) {
248 if (gelf_getphdr(elf, i, &p) == NULL) {
249 error(fname, "no segment data");
250 return;
251 }
252 if ((!(p.p_flags & PF_W)) &&
253 (p.p_type == PT_LOAD) && !(Fflag)) {
254 First += p.p_filesz;
255 } else if ((p.p_flags & PF_W) &&
256 (p.p_type == PT_LOAD) && !(Fflag)) {
257 Second += p.p_filesz;
258 Third += p.p_memsz;
259 }
260 memsize += p.p_memsz;
261 if ((p.p_type == PT_LOAD) && nflag) {
262 if (notfirst) {
263 (void) printf(" + ");
264 }
265 (void) printf(prusect[numbase], p.p_memsz);
266 total += p.p_memsz;
267 notfirst++;
268 }
269 if (!(p.p_type == PT_LOAD) && nflag) {
270 if (notfirst) {
271 (void) printf(" + ");
272 }
273 (void) printf(prusect[numbase], p.p_filesz);
274 total += p.p_filesz;
275 notfirst++;
276 }
277 if ((p.p_type == PT_LOAD) && Fflag && !nflag) {
278 if (notfirst) {
279 (void) printf(" + ");
280 }
281 (void) printf(prusect[numbase], p.p_memsz);
282 notfirst++;
283 }
284 if ((Fflag) && !(nflag) && (!(p.p_type == PT_LOAD))) {
285 continue;
286 }
287 if (Fflag || nflag) {
288 switch (p.p_flags) {
289 case 0: (void) printf("(---)"); break;
290 case PF_X: (void) printf("(--x)"); break;
291 case PF_W: (void) printf("(-w-)"); break;
292 case PF_W+PF_X: (void) printf("(-wx)"); break;
293 case PF_R: (void) printf("(r--)"); break;
294 case PF_R+PF_X: (void) printf("(r-x)"); break;
295 case PF_R+PF_W: (void) printf("(rw-)"); break;
296 case PF_R+PF_W+PF_X: (void) printf("(rwx)"); break;
297 default: (void) printf("flags(%#x)", p.p_flags);
298 }
299 }
300 }
301 if (nflag) {
302 (void) printf(prusum[numbase], total);
303 }
304 if (Fflag && !nflag) {
305 (void) printf(prusum[numbase], memsize);
306 }
307 if (!Fflag && !nflag) {
308 Totsize = First + Second + (Third - Second);
309 (void) printf(format[numbase],
310 First, Second, Third - Second, Totsize);
311 }
312 }
313