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 Fflag, /* full format for segments */
73 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 first,
87 second,
88 third,
89 totsize;
90 GElf_Ehdr ehdr;
91 GElf_Shdr shdr;
92 Elf_Scn *scn;
93 unsigned ndx = 0;
94 int numsect = 0;
95 int notfirst = 0;
96 int i;
97 char *name = 0;
98
99 /*
100 * If there is a program header and the -f flag requesting section infor-
101 * mation is not set, then process segments with the process_phdr function.
102 * Otherwise, process sections. For the default case, the first number
103 * shall be the size of all sections that are allocatable, nonwritable and
104 * not of type NOBITS; the second number shall be the size of all sections
105 * that are allocatable, writable, and not of type NOBITS; the third number
106 * is the size of all sections that are writable and not of type NOBITS.
107 * If -f is set, print the size of each allocatable section, followed by
108 * the section name in parentheses.
109 * If -n is set, print the size of all sections, followed by the section
110 * name in parentheses.
111 */
112
113 if (gelf_getehdr(elf, &ehdr) == 0) {
114 error(fname, "invalid file type");
115 return;
116 }
117 if ((ehdr.e_phnum != 0) && !(fflag)) {
118 process_phdr(elf, ehdr.e_phnum);
119 return;
120 }
121
122 if (is_archive) {
123 (void) printf("%s[%s]: ", archive, fname);
124 } else if (!oneflag && !is_archive) {
125 (void) printf("%s: ", fname);
126 }
127 ndx = ehdr.e_shstrndx;
128 scn = 0;
129 size = 0;
130 first = second = third = totsize = 0;
131 if (ehdr.e_shnum == 0) {
132 error(fname, "no section data");
133 }
134 numsect = ehdr.e_shnum;
135 for (i = 0; i < numsect; i++) {
136 if ((scn = elf_nextscn(elf, scn)) == 0) {
137 break;
138 }
139 if (gelf_getshdr(scn, &shdr) == 0) {
140 error(fname, "could not get section header");
141 break;
142 }
143 if ((Fflag) && !(fflag)) {
144 error(fname, "no segment data");
145 return;
146 } else if ((!(shdr.sh_flags & SHF_ALLOC)) &&
147 fflag && !(nflag)) {
148 continue;
149 } else if ((!(shdr.sh_flags & SHF_ALLOC)) && !(nflag)) {
150 continue;
151 } else if ((shdr.sh_flags & SHF_ALLOC) &&
152 (!(shdr.sh_flags & SHF_WRITE)) &&
153 (!(shdr.sh_type == SHT_NOBITS)) &&
154 !(fflag) && !(nflag)) {
155 first += shdr.sh_size;
156 } else if ((shdr.sh_flags & SHF_ALLOC) &&
157 (shdr.sh_flags & SHF_WRITE) &&
158 (!(shdr.sh_type == SHT_NOBITS)) &&
159 !(fflag) && !(nflag)) {
160 second += shdr.sh_size;
161 } else if ((shdr.sh_flags & SHF_WRITE) &&
162 (shdr.sh_type == SHT_NOBITS) &&
163 !(fflag) && !(nflag)) {
164 third += shdr.sh_size;
165 }
166 name = elf_strptr(elf, ndx, (size_t)shdr.sh_name);
167
168 if (fflag || nflag) {
169 size += shdr.sh_size;
170 if (notfirst) {
171 (void) printf(" + ");
172 }
173 (void) printf(prusect[numbase], shdr.sh_size);
174 (void) printf("(%s)", name);
175 }
176 notfirst++;
177 }
178 if ((fflag || nflag) && (numsect > 0)) {
179 (void) printf(prusum[numbase], size);
180 }
181
182 if (!fflag && !nflag) {
183 totsize = first + second + third;
184 (void) printf(format[numbase],
185 first, second, third, totsize);
186 }
187
188 if (Fflag) {
189 if (ehdr.e_phnum != 0) {
190 process_phdr(elf, ehdr.e_phnum);
191 return;
192 } else {
193 error(fname, "no segment data");
194 return;
195 }
196 }
197 }
198
199 /*
200 * If there is a program exection header, process segments. In the default
201 * case, the first number is the file size of all nonwritable segments
202 * of type PT_LOAD; the second number is the file size of all writable
203 * segments whose type is PT_LOAD; the third number is the memory size
204 * minus the file size of all writable segments of type PT_LOAD.
205 * If the -F flag is set, size will print the memory size of each loadable
206 * segment, followed by its permission flags.
207 * If -n is set, size will print the memory size of all loadable segments
208 * and the file size of all non-loadable segments, followed by their
209 * permission flags.
210 */
211
212 static void
process_phdr(Elf * elf,GElf_Half num)213 process_phdr(Elf * elf, GElf_Half num)
214 {
215 int i;
216 int notfirst = 0;
217 GElf_Phdr p;
218 GElf_Xword memsize,
219 total,
220 First,
221 Second,
222 Third,
223 Totsize;
224 extern int Fflag;
225 extern int nflag;
226 extern int numbase;
227 extern char *fname;
228 extern char *archive;
229 extern int is_archive;
230 extern int oneflag;
231
232 memsize = total = 0;
233 First = Second = Third = Totsize = 0;
234
235 if (is_archive) {
236 (void) printf("%s[%s]: ", archive, fname);
237 } else if (!oneflag && !is_archive) {
238 (void) printf("%s: ", fname);
239 }
240
241 for (i = 0; i < (int)num; i++) {
242 if (gelf_getphdr(elf, i, &p) == NULL) {
243 error(fname, "no segment data");
244 return;
245 }
246 if ((!(p.p_flags & PF_W)) &&
247 (p.p_type == PT_LOAD) && !(Fflag)) {
248 First += p.p_filesz;
249 } else if ((p.p_flags & PF_W) &&
250 (p.p_type == PT_LOAD) && !(Fflag)) {
251 Second += p.p_filesz;
252 Third += p.p_memsz;
253 }
254 memsize += p.p_memsz;
255 if ((p.p_type == PT_LOAD) && nflag) {
256 if (notfirst) {
257 (void) printf(" + ");
258 }
259 (void) printf(prusect[numbase], p.p_memsz);
260 total += p.p_memsz;
261 notfirst++;
262 }
263 if (!(p.p_type == PT_LOAD) && nflag) {
264 if (notfirst) {
265 (void) printf(" + ");
266 }
267 (void) printf(prusect[numbase], p.p_filesz);
268 total += p.p_filesz;
269 notfirst++;
270 }
271 if ((p.p_type == PT_LOAD) && Fflag && !nflag) {
272 if (notfirst) {
273 (void) printf(" + ");
274 }
275 (void) printf(prusect[numbase], p.p_memsz);
276 notfirst++;
277 }
278 if ((Fflag) && !(nflag) && (!(p.p_type == PT_LOAD))) {
279 continue;
280 }
281 if (Fflag || nflag) {
282 switch (p.p_flags) {
283 case 0: (void) printf("(---)"); break;
284 case PF_X: (void) printf("(--x)"); break;
285 case PF_W: (void) printf("(-w-)"); break;
286 case PF_W+PF_X: (void) printf("(-wx)"); break;
287 case PF_R: (void) printf("(r--)"); break;
288 case PF_R+PF_X: (void) printf("(r-x)"); break;
289 case PF_R+PF_W: (void) printf("(rw-)"); break;
290 case PF_R+PF_W+PF_X: (void) printf("(rwx)"); break;
291 default: (void) printf("flags(%#x)", p.p_flags);
292 }
293 }
294 }
295 if (nflag) {
296 (void) printf(prusum[numbase], total);
297 }
298 if (Fflag && !nflag) {
299 (void) printf(prusum[numbase], memsize);
300 }
301 if (!Fflag && !nflag) {
302 Totsize = First + Second + (Third - Second);
303 (void) printf(format[numbase],
304 First, Second, Third - Second, Totsize);
305 }
306 }
307