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