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