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 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 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