Changeset 1035

Show
Ignore:
Timestamp:
07/15/10 15:06:00 (4 years ago)
Author:
kaiwang27
Message:

Overhaul of table print out. Introduced new tbl_XXX functions for pretty
print of various sysv/bsd formatted tables. The improvements include:

* All the column width are computed by the new tbl_XXX functions internally.

Output table is formatted according to the spcified format and width.

* section name length no longer needs to computed before output and

sysv_calc() no longer needs to run twice.

* 64 bit address can now be printed correctly. (all internal counters promoted

to 64 bits)

Location:
trunk/size
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • trunk/size/Makefile

    r575 r1035  
    88DPADD=  ${LIBELF} 
    99 
     10CFLAGS+=        -g 
     11 
    1012.include "${TOP}/mk/elftoolchain.prog.mk" 
    1113 
  • trunk/size/size.c

    r1013 r1035  
    2626 
    2727#include <sys/cdefs.h> 
    28  
     28#include <assert.h> 
    2929#include <err.h> 
    3030#include <fcntl.h> 
     31#include <gelf.h> 
    3132#include <getopt.h> 
    3233#include <stdint.h> 
     
    3738#include <unistd.h> 
    3839 
    39 #include <libelf.h> 
    40 #include <gelf.h> 
    41  
    4240#include "_elftc.h" 
    4341 
    4442ELFTC_VCSID("$Id$"); 
    4543 
    46 #define BUF_SIZE                        40 
    47 #define DEFAULT_SECTION_NAME_LENGTH     19 
     44#define BUF_SIZE                        1024 
    4845#define ELF_ALIGN(val,x) (((val)+(x)-1) & ~((x)-1)) 
    4946#define SIZE_VERSION_STRING             "size 1.0" 
     
    9188}; 
    9289 
    93 uint32_t bss_size, data_size, text_size, total_size; 
    94 uint32_t bss_size_total, data_size_total, text_size_total; 
     90uint64_t bss_size, data_size, text_size, total_size; 
     91uint64_t bss_size_total, data_size_total, text_size_total; 
    9592 
    9693int show_totals; 
    9794 
    98 size_t sec_name_len     = DEFAULT_SECTION_NAME_LENGTH; 
    9995enum radix_style radix  = RADIX_DECIMAL; 
    10096enum output_style style = STYLE_BERKELEY; 
     97int elfclass            = ELFCLASS32; 
    10198 
    10299const char *default_args[2] = { "a.out", NULL }; 
     
    106103        OPT_RADIX 
    107104}; 
     105 
     106struct { 
     107        int row; 
     108        int col; 
     109        int *width; 
     110        char ***tbl; 
     111} *tb; 
    108112 
    109113int     size_option; 
     
    127131void    handle_phdr(Elf *, GElf_Ehdr *, GElf_Phdr *, uint32_t, 
    128132            const char *); 
    129 void    print_number(int, uint32_t, enum radix_style, char); 
    130133void    show_version(void); 
    131134void    sysv_header(const char *, Elf_Arhdr *); 
    132135void    sysv_footer(void); 
    133 void    sysv_calc(Elf *, GElf_Ehdr *, GElf_Shdr *, int); 
     136void    sysv_calc(Elf *, GElf_Ehdr *, GElf_Shdr *); 
    134137void    usage(void); 
     138void    tbl_new(int); 
     139void    tbl_print(const char *, int); 
     140void    tbl_print_num(uint64_t, enum radix_style, int); 
     141void    tbl_append(void); 
     142void    tbl_flush(void); 
    135143 
    136144/* 
     
    226234                files++; 
    227235        } 
    228         if (style == STYLE_BERKELEY && show_totals) 
    229                 berkeley_totals(); 
     236        if (style == STYLE_BERKELEY) { 
     237                if (show_totals) 
     238                        berkeley_totals(); 
     239                tbl_flush(); 
     240        } 
    230241        return (exitcode); 
    231242} 
     
    343354                                (void) snprintf(buf, BUF_SIZE, "%s/%d", 
    344355                                    ".reg", pid); 
    345                                 (void) printf("%-18s ", buf); 
    346                                 print_number(10, (uint32_t)raw_size, 
    347                                     radix, ' '); 
    348                                 print_number(10, (uint32_t)0, 
    349                                     radix, '\n'); 
     356                                tbl_append(); 
     357                                tbl_print(buf, 0); 
     358                                tbl_print_num(raw_size, radix, 1); 
     359                                tbl_print_num(0, radix, 2); 
    350360                                if (!reg_pseudo) { 
    351                                         (void) printf("%-18s ", ".reg"); 
    352                                         print_number(10, (uint32_t)raw_size, 
    353                                             radix, ' '); 
    354                                         print_number(10, (uint32_t)0, radix, 
    355                                             '\n'); 
     361                                        tbl_append(); 
     362                                        tbl_print(".reg", 0); 
     363                                        tbl_print_num(raw_size, radix, 1); 
     364                                        tbl_print_num(0, radix, 2); 
    356365                                        reg_pseudo = 1; 
    357366                                        text_size_total += raw_size; 
     
    365374                                (void) snprintf(buf, BUF_SIZE, 
    366375                                    "%s/%d", ".reg2", pid); 
    367                                 (void) printf("%-18s ", buf); 
    368                                 print_number(10, (uint32_t)nhdr_l.n_descsz, 
    369                                     radix, ' '); 
    370                                 print_number(10, (uint32_t)0, radix, '\n'); 
     376                                tbl_append(); 
     377                                tbl_print(buf, 0); 
     378                                tbl_print_num(nhdr_l.n_descsz, radix, 1); 
     379                                tbl_print_num(0, radix, 2); 
    371380                                if (!reg2_pseudo) { 
    372                                         (void) printf("%-18s ", ".reg2"); 
    373                                         print_number(10, 
    374                                             (uint32_t)nhdr_l.n_descsz, 
    375                                             radix, ' '); 
    376                                         print_number(10, (uint32_t)0, radix, 
    377                                             '\n'); 
     381                                        tbl_append(); 
     382                                        tbl_print(".reg2", 0); 
     383                                        tbl_print_num(nhdr_l.n_descsz, radix, 
     384                                            1); 
     385                                        tbl_print_num(0, radix, 2); 
    378386                                        reg2_pseudo = 1; 
    379387                                        text_size_total += nhdr_l.n_descsz; 
     
    384392                case NT_AUXV: 
    385393                        if (style == STYLE_SYSV) { 
    386                                 (void) printf("%-18s ", ".auxv"); 
    387                                 print_number(10, (uint32_t)nhdr_l.n_descsz, 
    388                                     radix, ' '); 
    389                                 print_number(10, (uint32_t)0, radix, '\n'); 
     394                                tbl_append(); 
     395                                tbl_print(".auxv", 0); 
     396                                tbl_print_num(nhdr_l.n_descsz, radix, 1); 
     397                                tbl_print_num(0, radix, 2); 
    390398                                text_size_total += nhdr_l.n_descsz; 
    391399                        } 
     
    393401                case NT_PRXFPREG: 
    394402                        if (style == STYLE_SYSV) { 
    395                                 (void) snprintf(buf, BUF_SIZE, 
    396                                     "%s/%d", ".reg-xfp", pid); 
    397                                 (void) printf("%-18s ", buf); 
    398                                 print_number(10, (uint32_t)nhdr_l.n_descsz, 
    399                                     radix, ' '); 
    400                                 print_number(10, (uint32_t)0, radix, '\n'); 
     403                                (void) snprintf(buf, BUF_SIZE, "%s/%d", 
     404                                    ".reg-xfp", pid); 
     405                                tbl_append(); 
     406                                tbl_print(buf, 0); 
     407                                tbl_print_num(nhdr_l.n_descsz, radix, 1); 
     408                                tbl_print_num(0, radix, 2); 
    401409                                if (!regxfp_pseudo) { 
    402                                         (void) printf("%-18s ", ".reg-xfp"); 
    403                                         print_number(10, 
    404                                             (uint32_t)nhdr_l.n_descsz, 
    405                                             radix, ' '); 
    406                                         print_number(10, (uint32_t)0, 
    407                                             radix, '\n'); 
     410                                        tbl_append(); 
     411                                        tbl_print(".reg-xfp", 0); 
     412                                        tbl_print_num(nhdr_l.n_descsz, radix, 
     413                                            1); 
     414                                        tbl_print_num(0, radix, 2); 
    408415                                        regxfp_pseudo = 1; 
    409416                                        text_size_total += nhdr_l.n_descsz; 
     
    457464    uint32_t idx, const char *name) 
    458465{ 
    459         uint32_t addr, size; 
     466        uint64_t addr, size; 
    460467        int split; 
    461468        char buf[BUF_SIZE]; 
     
    471478                (void) snprintf(buf, BUF_SIZE, 
    472479                    "%s%d%s", name, idx, (split ? "a" : "")); 
    473                 (void) printf("%-18s ", buf); 
    474                 print_number(10, (uint32_t)phdr->p_filesz, radix, ' '); 
    475                 print_number(10, (uint32_t)phdr->p_vaddr, radix, '\n'); 
     480                tbl_append(); 
     481                tbl_print(buf, 0); 
     482                tbl_print_num(phdr->p_filesz, radix, 1); 
     483                tbl_print_num(phdr->p_vaddr, radix, 2); 
    476484                text_size_total += phdr->p_filesz; 
    477485                if (split) { 
    478                         size = (uint32_t)(phdr->p_memsz - phdr->p_filesz); 
    479                         addr = (uint32_t)(phdr->p_vaddr + phdr->p_filesz); 
     486                        size = phdr->p_memsz - phdr->p_filesz; 
     487                        addr = phdr->p_vaddr + phdr->p_filesz; 
    480488                        (void) snprintf(buf, BUF_SIZE, "%s%d%s", name, 
    481489                            idx, "b"); 
    482490                        text_size_total += phdr->p_memsz - phdr->p_filesz; 
    483                         (void) printf("%-18s ", buf); 
    484                         print_number(10, size, radix, ' '); 
    485                         print_number(10, addr, radix, '\n'); 
     491                        tbl_append(); 
     492                        tbl_print(buf, 0); 
     493                        tbl_print_num(size, radix, 1); 
     494                        tbl_print_num(addr, radix, 2); 
    486495                } 
    487496        } else { 
     
    622631                        continue; 
    623632                } 
     633                elfclass = elfhdr.e_ident[EI_CLASS]; 
    624634                /* Core dumps are handled seperately */ 
    625635                if (elfhdr.e_shnum == 0 && elfhdr.e_type == ET_CORE) { 
     
    638648                                } 
    639649                        } else { 
    640                                 /* 
    641                                  * Perform a dry run to find the length of 
    642                                  * the largest segment name. 
    643                                  */ 
    644                                 while ((scn = elf_nextscn(elf, scn)) != NULL) { 
    645                                         if (gelf_getshdr(scn, &shdr) != NULL) { 
    646                                                 sysv_calc(elf, &elfhdr, 
    647                                                     &shdr, 1); 
    648                                         } 
    649                                 } 
    650650                                sysv_header(name, arhdr); 
    651651                                scn = NULL; 
    652652                                while ((scn = elf_nextscn(elf, scn)) != NULL) { 
    653653                                        if (gelf_getshdr(scn, &shdr) != NULL) 
    654                                                 sysv_calc(elf, &elfhdr, 
    655                                                     &shdr, 0); 
     654                                                sysv_calc(elf, &elfhdr, &shdr); 
    656655                                } 
    657656                        } 
     
    675674} 
    676675 
    677 void 
    678 print_number(int width, uint32_t num, enum radix_style rad, char c) 
    679 { 
    680         char buffer[BUF_SIZE]; 
    681  
    682         (void) snprintf(buffer, BUF_SIZE, (rad == RADIX_DECIMAL ? "%lu" : 
    683             ((rad == RADIX_OCTAL) ? "0%lo" : "0x%lx")), 
    684             (unsigned long int)num); 
    685         (void) printf("%-*s%c", width, buffer, c); 
    686 } 
    687  
    688676/* 
    689677 * Sysv formatting helper functions. 
     
    692680sysv_header(const char *name, Elf_Arhdr *arhdr) 
    693681{ 
     682 
    694683        text_size_total = 0; 
    695         if (arhdr != NULL) { 
    696                 (void) printf("%s   (ex %s):\n%-*s%-10s %-10s\n", 
    697                     arhdr->ar_name, name, (int)sec_name_len, 
    698                     "section","size","addr"); 
    699         } else { 
    700                 (void) printf("%s  :\n%-*s%-10s %-10s\n", 
    701                     name, (int)sec_name_len, "section", 
    702                     "size", "addr"); 
    703         } 
    704 } 
    705  
    706 void 
    707 sysv_calc(Elf *elf, GElf_Ehdr *elfhdr, GElf_Shdr *shdr, int dry_run) 
     684        if (arhdr != NULL) 
     685                (void) printf("%s   (ex %s):\n", arhdr->ar_name, name); 
     686        else 
     687                (void) printf("%s  :\n", name); 
     688        tbl_new(3); 
     689        tbl_append(); 
     690        tbl_print("section", 0); 
     691        tbl_print("size", 1); 
     692        tbl_print("addr", 2); 
     693} 
     694 
     695void 
     696sysv_calc(Elf *elf, GElf_Ehdr *elfhdr, GElf_Shdr *shdr) 
    708697{ 
    709698        char *section_name; 
    710699 
    711700        section_name = elf_strptr(elf, elfhdr->e_shstrndx, 
    712                                         (size_t)shdr->sh_name); 
    713         if (!dry_run) { 
    714                 if ((shdr->sh_type == SHT_SYMTAB || 
    715                     shdr->sh_type == SHT_STRTAB || shdr->sh_type == SHT_RELA || 
    716                     shdr->sh_type == SHT_REL) && shdr->sh_addr == 0) 
    717                         return; 
    718                 (void) printf("%-*s", (int)sec_name_len, section_name); 
    719                 print_number(10, (uint32_t)shdr->sh_size, radix, ' '); 
    720                 print_number(10, (uint32_t)shdr->sh_addr, radix, '\n'); 
    721                 text_size_total += shdr->sh_size; 
    722         } else { 
    723                 if (sec_name_len < strlen(section_name)) 
    724                         sec_name_len = strlen(section_name) + 3; 
    725         } 
     701            (size_t) shdr->sh_name); 
     702        if ((shdr->sh_type == SHT_SYMTAB || 
     703            shdr->sh_type == SHT_STRTAB || shdr->sh_type == SHT_RELA || 
     704            shdr->sh_type == SHT_REL) && shdr->sh_addr == 0) 
     705                return; 
     706        tbl_append(); 
     707        tbl_print(section_name, 0); 
     708        tbl_print_num(shdr->sh_size, radix, 1); 
     709        tbl_print_num(shdr->sh_addr, radix, 2); 
     710        text_size_total += shdr->sh_size; 
    726711} 
    727712 
     
    729714sysv_footer(void) 
    730715{ 
    731         (void) printf("%-*s", (int)sec_name_len, "Total"); 
    732         print_number(10, text_size_total, radix, '\n'); 
    733         (void) printf("\n"); 
     716        tbl_append(); 
     717        tbl_print("Total", 0); 
     718        tbl_print_num(text_size_total, radix, 1); 
     719        tbl_flush(); 
    734720} 
    735721 
     
    740726berkeley_header(void) 
    741727{ 
     728        static int printed; 
     729 
    742730        text_size = data_size = bss_size = 0; 
     731        if (!printed) { 
     732                tbl_new(6); 
     733                tbl_append(); 
     734                tbl_print("text", 0); 
     735                tbl_print("data", 1); 
     736                tbl_print("bss", 2); 
     737                if (radix == RADIX_OCTAL) 
     738                        tbl_print("oct", 3); 
     739                else 
     740                        tbl_print("dec", 3); 
     741                tbl_print("hex", 4); 
     742                tbl_print("filename", 5); 
     743                printed = 1; 
     744        } 
    743745} 
    744746 
     
    768770 
    769771        grand_total = text_size_total + data_size_total + bss_size_total; 
    770         print_number(10, text_size_total, radix, ' '); 
    771         print_number(10, data_size_total, radix, ' '); 
    772         print_number(10, bss_size_total, radix, ' '); 
     772        tbl_append(); 
     773        tbl_print_num(text_size_total, radix, 0); 
     774        tbl_print_num(data_size_total, radix, 1); 
     775        tbl_print_num(bss_size_total, radix, 2); 
    773776        if (radix == RADIX_OCTAL) 
    774                 print_number(10, grand_total, RADIX_OCTAL, ' '); 
     777                tbl_print_num(grand_total, RADIX_OCTAL, 3); 
    775778        else 
    776                 print_number(10, grand_total, RADIX_DECIMAL, ' '); 
    777         (void) printf("%-10lx (TOTALS)\n", grand_total); 
     779                tbl_print_num(grand_total, RADIX_DECIMAL, 3); 
     780        tbl_print_num(grand_total, RADIX_HEX, 4); 
    778781} 
    779782 
     
    781784berkeley_footer(const char *name, const char *ar_name, const char *msg) 
    782785{ 
    783         static int header_printed; 
    784         const char *col_name; 
    785  
    786         if (!header_printed) { 
    787                 (radix == RADIX_OCTAL) ? (col_name = "oct") : 
    788                     (col_name = "dec"); 
    789                 (void) printf("%-10s %-10s %-10s %-10s %-10s filename\n", 
    790                     "text","data","bss",col_name,"hex"); 
    791                 header_printed = 1; 
    792         } 
     786        char buf[BUF_SIZE]; 
    793787 
    794788        total_size = text_size + data_size + bss_size; 
     
    799793        } 
    800794 
    801         print_number(10, text_size, radix, ' '); 
    802         print_number(10, data_size, radix, ' '); 
    803         print_number(10, bss_size, radix, ' '); 
     795        tbl_append(); 
     796        tbl_print_num(text_size, radix, 0); 
     797        tbl_print_num(data_size, radix, 1); 
     798        tbl_print_num(bss_size, radix, 2); 
    804799        if (radix == RADIX_OCTAL) 
    805                 print_number(10, total_size, RADIX_OCTAL, ' '); 
     800                tbl_print_num(total_size, RADIX_OCTAL, 3); 
    806801        else 
    807                 print_number(10, total_size, RADIX_DECIMAL, ' '); 
    808         (void) printf("%-10lx\t", (long unsigned int)total_size); 
     802                tbl_print_num(total_size, RADIX_DECIMAL, 3); 
     803        tbl_print_num(total_size, RADIX_HEX, 4); 
    809804        if (ar_name != NULL && name != NULL) 
    810                 (void) printf("%s (%s %s)\n", ar_name, msg, name); 
     805                (void) snprintf(buf, BUF_SIZE, "%s (%s %s)", ar_name, msg, 
     806                    name); 
    811807        else if (ar_name != NULL && name == NULL) 
    812                 (void) printf("%s (%s)\n", ar_name, msg); 
     808                (void) snprintf(buf, BUF_SIZE, "%s (%s)", ar_name, msg); 
    813809        else 
    814                 (void) printf("%s\n", name); 
     810                (void) snprintf(buf, BUF_SIZE, "%s", name); 
     811        tbl_print(buf, 5); 
     812} 
     813 
     814 
     815void 
     816tbl_new(int col) 
     817{ 
     818 
     819        assert(tb == NULL); 
     820        assert(col > 0); 
     821        if ((tb = calloc(1, sizeof(*tb))) == NULL) 
     822                err(EX_SOFTWARE, "calloc"); 
     823        if ((tb->tbl = calloc(col, sizeof(*tb->tbl))) == NULL) 
     824                err(EX_SOFTWARE, "calloc"); 
     825        if ((tb->width = calloc(col, sizeof(*tb->width))) == NULL) 
     826                err(EX_SOFTWARE, "calloc"); 
     827        tb->col = col; 
     828        tb->row = 0; 
     829} 
     830 
     831void 
     832tbl_print(const char *s, int col) 
     833{ 
     834        int len; 
     835 
     836        assert(tb != NULL && tb->col > 0 && tb->row > 0 && col < tb->col); 
     837        assert(s != NULL && tb->tbl[col][tb->row - 1] == NULL); 
     838        if ((tb->tbl[col][tb->row - 1] = strdup(s)) == NULL) 
     839                err(EX_SOFTWARE, "strdup"); 
     840        len = strlen(s); 
     841        if (len > tb->width[col]) 
     842                tb->width[col] = len; 
     843} 
     844 
     845void 
     846tbl_print_num(uint64_t num, enum radix_style rad, int col) 
     847{ 
     848        char buf[BUF_SIZE]; 
     849 
     850        (void) snprintf(buf, BUF_SIZE, (rad == RADIX_DECIMAL ? "%ju" : 
     851            ((rad == RADIX_OCTAL) ? "0%jo" : "0x%jx")), (uintmax_t) num); 
     852        tbl_print(buf, col); 
     853} 
     854 
     855void 
     856tbl_append(void) 
     857{ 
     858        int i; 
     859 
     860        assert(tb != NULL && tb->col > 0); 
     861        tb->row++; 
     862        for (i = 0; i < tb->col; i++) { 
     863                tb->tbl[i] = realloc(tb->tbl[i], sizeof(*tb->tbl[i]) * tb->row); 
     864                if (tb->tbl[i] == NULL) 
     865                        err(EX_SOFTWARE, "realloc"); 
     866                tb->tbl[i][tb->row - 1] = NULL; 
     867        } 
     868} 
     869 
     870void 
     871tbl_flush(void) 
     872{ 
     873        const char *str; 
     874        int i, j; 
     875 
     876        assert(tb != NULL && tb->col > 0); 
     877        for (i = 0; i < tb->row; i++) { 
     878                if (style == STYLE_BERKELEY) 
     879                        printf("  "); 
     880                for (j = 0; j < tb->col; j++) { 
     881                        str = (tb->tbl[j][i] != NULL ? tb->tbl[j][i] : ""); 
     882                        if (style == STYLE_SYSV && j == 0) 
     883                                printf("%-*s", tb->width[j], str); 
     884                        else if (style == STYLE_BERKELEY && j == tb->col - 1) 
     885                                printf("%s", str); 
     886                        else 
     887                                printf("%*s", tb->width[j], str); 
     888                        if (j == tb->col -1) 
     889                                putchar('\n'); 
     890                        else 
     891                                printf("   "); 
     892                } 
     893        } 
     894 
     895        for (i = 0; i < tb->col; i++) { 
     896                for (j = 0; j < tb->row; j++) { 
     897                        if (tb->tbl[i][j]) 
     898                                free(tb->tbl[i][j]); 
     899                } 
     900                free(tb->tbl[i]); 
     901        } 
     902        free(tb); 
     903        tb = NULL; 
    815904} 
    816905