2 * Copyright (c) 2007 S.Sam Arun Raj
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 ELFTC_VCSID("$Id: size.c 3458 2016-05-09 15:01:25Z emaste $");
44 #define ELF_ALIGN(val,x) (((val)+(x)-1) & ~((x)-1))
45 #define SIZE_VERSION_STRING "size 1.0"
65 static uint64_t bss_size
, data_size
, text_size
, total_size
;
66 static uint64_t bss_size_total
, data_size_total
, text_size_total
;
67 static int show_totals
;
68 static int size_option
;
69 static enum radix_style radix
= RADIX_DECIMAL
;
70 static enum output_style style
= STYLE_BERKELEY
;
71 static const char *default_args
[2] = { "a.out", NULL
};
85 static struct option size_longopts
[] = {
86 { "format", required_argument
, &size_option
, OPT_FORMAT
},
87 { "help", no_argument
, NULL
, 'h' },
88 { "radix", required_argument
, &size_option
, OPT_RADIX
},
89 { "totals", no_argument
, NULL
, 't' },
90 { "version", no_argument
, NULL
, 'V' },
94 static void berkeley_calc(GElf_Shdr
*);
95 static void berkeley_footer(const char *, const char *, const char *);
96 static void berkeley_header(void);
97 static void berkeley_totals(void);
98 static int handle_core(char const *, Elf
*elf
, GElf_Ehdr
*);
99 static void handle_core_note(Elf
*, GElf_Ehdr
*, GElf_Phdr
*, char **);
100 static int handle_elf(char const *);
101 static void handle_phdr(Elf
*, GElf_Ehdr
*, GElf_Phdr
*, uint32_t,
103 static void show_version(void);
104 static void sysv_header(const char *, Elf_Arhdr
*);
105 static void sysv_footer(void);
106 static void sysv_calc(Elf
*, GElf_Ehdr
*, GElf_Shdr
*);
107 static void usage(void);
108 static void tbl_new(int);
109 static void tbl_print(const char *, int);
110 static void tbl_print_num(uint64_t, enum radix_style
, int);
111 static void tbl_append(void);
112 static void tbl_flush(void);
115 * size utility using elf(3) and gelf(3) API to list section sizes and
116 * total in elf files. Supports only elf files (core dumps in elf
117 * included) that can be opened by libelf, other formats are not supported.
120 main(int argc
, char **argv
)
123 const char **files
, *fn
;
127 if (elf_version(EV_CURRENT
) == EV_NONE
)
128 errx(EXIT_FAILURE
, "ELF library initialization failed: %s",
131 while ((ch
= getopt_long(argc
, argv
, "ABVdhotx", size_longopts
,
138 style
= STYLE_BERKELEY
;
144 radix
= RADIX_DECIMAL
;
156 switch (size_option
) {
158 if (*optarg
== 's' || *optarg
== 'S')
160 else if (*optarg
== 'b' || *optarg
== 'B')
161 style
= STYLE_BERKELEY
;
163 warnx("unrecognized format \"%s\".",
169 r
= strtol(optarg
, NULL
, 10);
173 radix
= RADIX_DECIMAL
;
177 warnx("unsupported radix \"%s\".",
183 err(EXIT_FAILURE
, "Error in option handling.");
196 files
= (argc
== 0) ? default_args
: (void *) argv
;
198 while ((fn
= *files
) != NULL
) {
201 warnx(rc
== RETURN_NOINPUT
?
202 "'%s': No such file" :
203 "%s: File format not recognized", fn
);
206 if (style
== STYLE_BERKELEY
) {
215 xlatetom(Elf
*elf
, GElf_Ehdr
*elfhdr
, void *_src
, void *_dst
,
216 Elf_Type type
, size_t size
)
222 src
.d_version
= elfhdr
->e_version
;
225 dst
.d_version
= elfhdr
->e_version
;
227 return (gelf_xlatetom(elf
, &dst
, &src
, elfhdr
->e_ident
[EI_DATA
]));
230 #define NOTE_OFFSET_32(nhdr, namesz, offset) \
231 ((char *)nhdr + sizeof(Elf32_Nhdr) + \
232 ELF_ALIGN((int32_t)namesz, 4) + offset)
234 #define NOTE_OFFSET_64(nhdr, namesz, offset) \
235 ((char *)nhdr + sizeof(Elf32_Nhdr) + \
236 ELF_ALIGN((int32_t)namesz, 8) + offset)
238 #define PID32(nhdr, namesz, offset) \
239 (pid_t)*((int *)((uintptr_t)NOTE_OFFSET_32(nhdr, \
242 #define PID64(nhdr, namesz, offset) \
243 (pid_t)*((int *)((uintptr_t)NOTE_OFFSET_64(nhdr, \
246 #define NEXT_NOTE(elfhdr, descsz, namesz, offset) do { \
247 if (elfhdr->e_ident[EI_CLASS] == ELFCLASS32) { \
248 offset += ELF_ALIGN((int32_t)descsz, 4) + \
249 sizeof(Elf32_Nhdr) + \
250 ELF_ALIGN((int32_t)namesz, 4); \
252 offset += ELF_ALIGN((int32_t)descsz, 8) + \
253 sizeof(Elf32_Nhdr) + \
254 ELF_ALIGN((int32_t)namesz, 8); \
259 * Parse individual note entries inside a PT_NOTE segment.
262 handle_core_note(Elf
*elf
, GElf_Ehdr
*elfhdr
, GElf_Phdr
*phdr
,
265 size_t max_size
, segment_end
;
270 Elf32_Nhdr
*nhdr
, nhdr_l
;
271 static int reg_pseudo
= 0, reg2_pseudo
= 0, regxfp_pseudo
= 0;
272 char buf
[BUF_SIZE
], *data
, *name
;
274 if (elf
== NULL
|| elfhdr
== NULL
|| phdr
== NULL
)
277 data
= elf_rawfile(elf
, &max_size
);
278 offset
= phdr
->p_offset
;
279 if (offset
>= max_size
|| phdr
->p_filesz
> max_size
- offset
) {
280 warnx("invalid PHDR offset");
283 segment_end
= phdr
->p_offset
+ phdr
->p_filesz
;
285 while (data
!= NULL
&& offset
+ sizeof(Elf32_Nhdr
) < segment_end
) {
286 nhdr
= (Elf32_Nhdr
*)(uintptr_t)((char*)data
+ offset
);
287 memset(&nhdr_l
, 0, sizeof(Elf32_Nhdr
));
288 if (!xlatetom(elf
, elfhdr
, &nhdr
->n_type
, &nhdr_l
.n_type
,
289 ELF_T_WORD
, sizeof(Elf32_Word
)) ||
290 !xlatetom(elf
, elfhdr
, &nhdr
->n_descsz
, &nhdr_l
.n_descsz
,
291 ELF_T_WORD
, sizeof(Elf32_Word
)) ||
292 !xlatetom(elf
, elfhdr
, &nhdr
->n_namesz
, &nhdr_l
.n_namesz
,
293 ELF_T_WORD
, sizeof(Elf32_Word
)))
296 if (offset
+ sizeof(Elf32_Nhdr
) +
297 ELF_ALIGN(nhdr_l
.n_namesz
, 4) +
298 ELF_ALIGN(nhdr_l
.n_descsz
, 4) >= segment_end
) {
299 warnx("invalid note header");
303 name
= (char *)((char *)nhdr
+ sizeof(Elf32_Nhdr
));
304 switch (nhdr_l
.n_type
) {
307 if (elfhdr
->e_ident
[EI_OSABI
] == ELFOSABI_FREEBSD
&&
308 nhdr_l
.n_namesz
== 0x8 &&
309 !strcmp(name
,"FreeBSD")) {
310 if (elfhdr
->e_ident
[EI_CLASS
] == ELFCLASS32
) {
311 raw_size
= (uint64_t)*((uint32_t *)
314 nhdr_l
.n_namesz
, 4) + 8));
315 ver
= (uintptr_t)NOTE_OFFSET_32(nhdr
,
317 if (*((int *)ver
) == 1)
319 nhdr_l
.n_namesz
, 24);
321 raw_size
= *((uint64_t *)(uintptr_t)
322 (name
+ ELF_ALIGN((int32_t)
323 nhdr_l
.n_namesz
, 8) + 16));
324 ver
= (uintptr_t)NOTE_OFFSET_64(nhdr
,
326 if (*((int *)ver
) == 1)
328 nhdr_l
.n_namesz
, 40);
330 xlatetom(elf
, elfhdr
, &raw_size
, &raw_size
,
331 ELF_T_WORD
, sizeof(uint64_t));
332 xlatetom(elf
, elfhdr
, &pid
, &pid
, ELF_T_WORD
,
336 if (raw_size
!= 0 && style
== STYLE_SYSV
) {
337 (void) snprintf(buf
, BUF_SIZE
, "%s/%d",
341 tbl_print_num(raw_size
, radix
, 1);
342 tbl_print_num(0, radix
, 2);
345 tbl_print(".reg", 0);
346 tbl_print_num(raw_size
, radix
, 1);
347 tbl_print_num(0, radix
, 2);
349 text_size_total
+= raw_size
;
351 text_size_total
+= raw_size
;
355 case NT_FPREGSET
: /* same as NT_PRFPREG */
356 if (style
== STYLE_SYSV
) {
357 (void) snprintf(buf
, BUF_SIZE
,
358 "%s/%d", ".reg2", pid
);
361 tbl_print_num(nhdr_l
.n_descsz
, radix
, 1);
362 tbl_print_num(0, radix
, 2);
365 tbl_print(".reg2", 0);
366 tbl_print_num(nhdr_l
.n_descsz
, radix
,
368 tbl_print_num(0, radix
, 2);
370 text_size_total
+= nhdr_l
.n_descsz
;
372 text_size_total
+= nhdr_l
.n_descsz
;
376 if (style
== STYLE_SYSV
) {
378 tbl_print(".auxv", 0);
379 tbl_print_num(nhdr_l
.n_descsz
, radix
, 1);
380 tbl_print_num(0, radix
, 2);
381 text_size_total
+= nhdr_l
.n_descsz
;
385 if (style
== STYLE_SYSV
) {
386 (void) snprintf(buf
, BUF_SIZE
, "%s/%d",
390 tbl_print_num(nhdr_l
.n_descsz
, radix
, 1);
391 tbl_print_num(0, radix
, 2);
392 if (!regxfp_pseudo
) {
394 tbl_print(".reg-xfp", 0);
395 tbl_print_num(nhdr_l
.n_descsz
, radix
,
397 tbl_print_num(0, radix
, 2);
399 text_size_total
+= nhdr_l
.n_descsz
;
401 text_size_total
+= nhdr_l
.n_descsz
;
407 if (nhdr_l
.n_descsz
== 0x78 &&
408 !strcmp(name
,"FreeBSD")) {
409 *cmd_line
= strdup(NOTE_OFFSET_64(nhdr
,
410 nhdr_l
.n_namesz
, 33));
412 } else if (nhdr_l
.n_descsz
== 0x6c &&
413 !strcmp(name
,"FreeBSD")) {
414 *cmd_line
= strdup(NOTE_OFFSET_32(nhdr
,
415 nhdr_l
.n_namesz
, 25));
417 /* Strip any trailing spaces */
418 if (*cmd_line
!= NULL
) {
421 s
= *cmd_line
+ strlen(*cmd_line
);
422 while (s
> *cmd_line
) {
423 if (*(s
-1) != 0x20) break;
435 NEXT_NOTE(elfhdr
, nhdr_l
.n_descsz
, nhdr_l
.n_namesz
, offset
);
440 * Handles program headers except for PT_NOTE, when sysv output style is
441 * chosen, prints out the segment name and length. For berkely output
442 * style only PT_LOAD segments are handled, and text,
443 * data, bss size is calculated for them.
446 handle_phdr(Elf
*elf
, GElf_Ehdr
*elfhdr
, GElf_Phdr
*phdr
,
447 uint32_t idx
, const char *name
)
453 if (elf
== NULL
|| elfhdr
== NULL
|| phdr
== NULL
)
456 split
= (phdr
->p_memsz
> 0) && (phdr
->p_filesz
> 0) &&
457 (phdr
->p_memsz
> phdr
->p_filesz
);
459 if (style
== STYLE_SYSV
) {
460 (void) snprintf(buf
, BUF_SIZE
,
461 "%s%d%s", name
, idx
, (split
? "a" : ""));
464 tbl_print_num(phdr
->p_filesz
, radix
, 1);
465 tbl_print_num(phdr
->p_vaddr
, radix
, 2);
466 text_size_total
+= phdr
->p_filesz
;
468 size
= phdr
->p_memsz
- phdr
->p_filesz
;
469 addr
= phdr
->p_vaddr
+ phdr
->p_filesz
;
470 (void) snprintf(buf
, BUF_SIZE
, "%s%d%s", name
,
472 text_size_total
+= phdr
->p_memsz
- phdr
->p_filesz
;
475 tbl_print_num(size
, radix
, 1);
476 tbl_print_num(addr
, radix
, 2);
479 if (phdr
->p_type
!= PT_LOAD
)
481 if ((phdr
->p_flags
& PF_W
) && !(phdr
->p_flags
& PF_X
)) {
482 data_size
+= phdr
->p_filesz
;
484 data_size
+= phdr
->p_memsz
- phdr
->p_filesz
;
486 text_size
+= phdr
->p_filesz
;
488 text_size
+= phdr
->p_memsz
- phdr
->p_filesz
;
494 * Given a core dump file, this function maps program headers to segments.
497 handle_core(char const *name
, Elf
*elf
, GElf_Ehdr
*elfhdr
)
502 const char *seg_name
;
504 if (name
== NULL
|| elf
== NULL
|| elfhdr
== NULL
)
505 return (RETURN_DATAERR
);
506 if (elfhdr
->e_shnum
!= 0 || elfhdr
->e_type
!= ET_CORE
)
507 return (RETURN_DATAERR
);
509 seg_name
= core_cmdline
= NULL
;
510 if (style
== STYLE_SYSV
)
511 sysv_header(name
, NULL
);
515 for (i
= 0; i
< elfhdr
->e_phnum
; i
++) {
516 if (gelf_getphdr(elf
, i
, &phdr
) != NULL
) {
517 if (phdr
.p_type
== PT_NOTE
) {
518 handle_phdr(elf
, elfhdr
, &phdr
, i
, "note");
519 handle_core_note(elf
, elfhdr
, &phdr
,
522 switch(phdr
.p_type
) {
530 seg_name
= "dynamic";
541 case PT_GNU_EH_FRAME
:
542 seg_name
= "eh_frame_hdr";
548 seg_name
= "segment";
550 handle_phdr(elf
, elfhdr
, &phdr
, i
, seg_name
);
555 if (style
== STYLE_BERKELEY
) {
556 if (core_cmdline
!= NULL
) {
557 berkeley_footer(core_cmdline
, name
,
558 "core file invoked as");
560 berkeley_footer(core_cmdline
, name
, "core file");
564 if (core_cmdline
!= NULL
) {
565 (void) printf(" (core file invoked as %s)\n\n",
568 (void) printf(" (core file)\n\n");
576 * Given an elf object,ar(1) filename, and based on the output style
577 * and radix format the various sections and their length will be printed
578 * or the size of the text, data, bss sections will be printed out.
581 handle_elf(char const *name
)
592 return (RETURN_NOINPUT
);
594 if ((fd
= open(name
, O_RDONLY
, 0)) < 0)
595 return (RETURN_NOINPUT
);
597 elf_cmd
= ELF_C_READ
;
598 elf1
= elf_begin(fd
, elf_cmd
, NULL
);
599 while ((elf
= elf_begin(fd
, elf_cmd
, elf1
)) != NULL
) {
600 arhdr
= elf_getarhdr(elf
);
601 if (elf_kind(elf
) == ELF_K_NONE
&& arhdr
== NULL
) {
603 (void) elf_end(elf1
);
605 return (RETURN_DATAERR
);
607 if (elf_kind(elf
) != ELF_K_ELF
||
608 (gelf_getehdr(elf
, &elfhdr
) == NULL
)) {
609 elf_cmd
= elf_next(elf
);
611 warnx("%s: File format not recognized",
612 arhdr
!= NULL
? arhdr
->ar_name
: name
);
615 /* Core dumps are handled separately */
616 if (elfhdr
.e_shnum
== 0 && elfhdr
.e_type
== ET_CORE
) {
617 exit_code
= handle_core(name
, elf
, &elfhdr
);
619 (void) elf_end(elf1
);
624 if (style
== STYLE_BERKELEY
) {
626 while ((scn
= elf_nextscn(elf
, scn
)) != NULL
) {
627 if (gelf_getshdr(scn
, &shdr
) != NULL
)
628 berkeley_calc(&shdr
);
631 sysv_header(name
, arhdr
);
633 while ((scn
= elf_nextscn(elf
, scn
)) != NULL
) {
634 if (gelf_getshdr(scn
, &shdr
) != NULL
)
635 sysv_calc(elf
, &elfhdr
, &shdr
);
638 if (style
== STYLE_BERKELEY
) {
640 berkeley_footer(name
, arhdr
->ar_name
,
643 berkeley_footer(name
, NULL
, "ex");
649 elf_cmd
= elf_next(elf
);
652 (void) elf_end(elf1
);
658 * Sysv formatting helper functions.
661 sysv_header(const char *name
, Elf_Arhdr
*arhdr
)
666 (void) printf("%s (ex %s):\n", arhdr
->ar_name
, name
);
668 (void) printf("%s :\n", name
);
671 tbl_print("section", 0);
672 tbl_print("size", 1);
673 tbl_print("addr", 2);
677 sysv_calc(Elf
*elf
, GElf_Ehdr
*elfhdr
, GElf_Shdr
*shdr
)
681 section_name
= elf_strptr(elf
, elfhdr
->e_shstrndx
,
682 (size_t) shdr
->sh_name
);
683 if ((shdr
->sh_type
== SHT_SYMTAB
||
684 shdr
->sh_type
== SHT_STRTAB
|| shdr
->sh_type
== SHT_RELA
||
685 shdr
->sh_type
== SHT_REL
) && shdr
->sh_addr
== 0)
688 tbl_print(section_name
, 0);
689 tbl_print_num(shdr
->sh_size
, radix
, 1);
690 tbl_print_num(shdr
->sh_addr
, radix
, 2);
691 text_size_total
+= shdr
->sh_size
;
698 tbl_print("Total", 0);
699 tbl_print_num(text_size_total
, radix
, 1);
705 * berkeley style output formatting helper functions.
708 berkeley_header(void)
712 text_size
= data_size
= bss_size
= 0;
716 tbl_print("text", 0);
717 tbl_print("data", 1);
719 if (radix
== RADIX_OCTAL
)
724 tbl_print("filename", 5);
730 berkeley_calc(GElf_Shdr
*shdr
)
733 if (!(shdr
->sh_flags
& SHF_ALLOC
))
735 if ((shdr
->sh_flags
& SHF_ALLOC
) &&
736 ((shdr
->sh_flags
& SHF_EXECINSTR
) ||
737 !(shdr
->sh_flags
& SHF_WRITE
)))
738 text_size
+= shdr
->sh_size
;
739 else if ((shdr
->sh_flags
& SHF_ALLOC
) &&
740 (shdr
->sh_flags
& SHF_WRITE
) &&
741 (shdr
->sh_type
!= SHT_NOBITS
))
742 data_size
+= shdr
->sh_size
;
744 bss_size
+= shdr
->sh_size
;
749 berkeley_totals(void)
751 uint64_t grand_total
;
753 grand_total
= text_size_total
+ data_size_total
+ bss_size_total
;
755 tbl_print_num(text_size_total
, radix
, 0);
756 tbl_print_num(data_size_total
, radix
, 1);
757 tbl_print_num(bss_size_total
, radix
, 2);
758 if (radix
== RADIX_OCTAL
)
759 tbl_print_num(grand_total
, RADIX_OCTAL
, 3);
761 tbl_print_num(grand_total
, RADIX_DECIMAL
, 3);
762 tbl_print_num(grand_total
, RADIX_HEX
, 4);
766 berkeley_footer(const char *name
, const char *ar_name
, const char *msg
)
770 total_size
= text_size
+ data_size
+ bss_size
;
772 text_size_total
+= text_size
;
773 bss_size_total
+= bss_size
;
774 data_size_total
+= data_size
;
778 tbl_print_num(text_size
, radix
, 0);
779 tbl_print_num(data_size
, radix
, 1);
780 tbl_print_num(bss_size
, radix
, 2);
781 if (radix
== RADIX_OCTAL
)
782 tbl_print_num(total_size
, RADIX_OCTAL
, 3);
784 tbl_print_num(total_size
, RADIX_DECIMAL
, 3);
785 tbl_print_num(total_size
, RADIX_HEX
, 4);
786 if (ar_name
!= NULL
&& name
!= NULL
)
787 (void) snprintf(buf
, BUF_SIZE
, "%s (%s %s)", ar_name
, msg
,
789 else if (ar_name
!= NULL
&& name
== NULL
)
790 (void) snprintf(buf
, BUF_SIZE
, "%s (%s)", ar_name
, msg
);
792 (void) snprintf(buf
, BUF_SIZE
, "%s", name
);
803 if ((tb
= calloc(1, sizeof(*tb
))) == NULL
)
804 err(EXIT_FAILURE
, "calloc");
805 if ((tb
->tbl
= calloc(col
, sizeof(*tb
->tbl
))) == NULL
)
806 err(EXIT_FAILURE
, "calloc");
807 if ((tb
->width
= calloc(col
, sizeof(*tb
->width
))) == NULL
)
808 err(EXIT_FAILURE
, "calloc");
814 tbl_print(const char *s
, int col
)
818 assert(tb
!= NULL
&& tb
->col
> 0 && tb
->row
> 0 && col
< tb
->col
);
819 assert(s
!= NULL
&& tb
->tbl
[col
][tb
->row
- 1] == NULL
);
820 if ((tb
->tbl
[col
][tb
->row
- 1] = strdup(s
)) == NULL
)
821 err(EXIT_FAILURE
, "strdup");
823 if (len
> tb
->width
[col
])
824 tb
->width
[col
] = len
;
828 tbl_print_num(uint64_t num
, enum radix_style rad
, int col
)
832 (void) snprintf(buf
, BUF_SIZE
, (rad
== RADIX_DECIMAL
? "%ju" :
833 ((rad
== RADIX_OCTAL
) ? "0%jo" : "0x%jx")), (uintmax_t) num
);
842 assert(tb
!= NULL
&& tb
->col
> 0);
844 for (i
= 0; i
< tb
->col
; i
++) {
845 tb
->tbl
[i
] = realloc(tb
->tbl
[i
], sizeof(*tb
->tbl
[i
]) * tb
->row
);
846 if (tb
->tbl
[i
] == NULL
)
847 err(EXIT_FAILURE
, "realloc");
848 tb
->tbl
[i
][tb
->row
- 1] = NULL
;
862 for (i
= 0; i
< tb
->row
; i
++) {
863 if (style
== STYLE_BERKELEY
)
865 for (j
= 0; j
< tb
->col
; j
++) {
866 str
= (tb
->tbl
[j
][i
] != NULL
? tb
->tbl
[j
][i
] : "");
867 if (style
== STYLE_SYSV
&& j
== 0)
868 printf("%-*s", tb
->width
[j
], str
);
869 else if (style
== STYLE_BERKELEY
&& j
== tb
->col
- 1)
872 printf("%*s", tb
->width
[j
], str
);
880 for (i
= 0; i
< tb
->col
; i
++) {
881 for (j
= 0; j
< tb
->row
; j
++) {
893 #define USAGE_MESSAGE "\
894 Usage: %s [options] file ...\n\
895 Display sizes of ELF sections.\n\n\
897 --format=format Display output in specified format. Supported\n\
898 values are `berkeley' and `sysv'.\n\
899 --help Display this help message and exit.\n\
900 --radix=radix Display numeric values in the specified radix.\n\
901 Supported values are: 8, 10 and 16.\n\
902 --totals Show cumulative totals of section sizes.\n\
903 --version Display a version identifier and exit.\n\
904 -A Equivalent to `--format=sysv'.\n\
905 -B Equivalent to `--format=berkeley'.\n\
906 -V Equivalent to `--version'.\n\
907 -d Equivalent to `--radix=10'.\n\
908 -h Same as option --help.\n\
909 -o Equivalent to `--radix=8'.\n\
910 -t Equivalent to option --totals.\n\
911 -x Equivalent to `--radix=16'.\n"
916 (void) fprintf(stderr
, USAGE_MESSAGE
, ELFTC_GETPROGNAME());
923 (void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version());