#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "stuff/bool.h"
#include "stuff/ofile.h"
#include "stuff/errors.h"
#include "stuff/allocate.h"
char *progname = NULL;
struct flags {
unsigned long nfiles;
enum bool m;
enum bool l;
enum bool x;
};
static void usage(
void);
static void size(
struct ofile *ofile,
char *arch_name,
void *cookie);
int
main(
int argc,
char **argv,
char **envp)
{
int i;
enum bool args_left;
struct flags flag;
struct arch_flag *arch_flags;
unsigned long narch_flags;
enum bool all_archs;
progname = argv[0];
arch_flags = NULL;
narch_flags = 0;
all_archs = FALSE;
flag.nfiles = 0;
flag.m = FALSE;
flag.l = FALSE;
flag.x = FALSE;
for(i = 1; i < argc; i++){
if(argv[i][0] == '-'){
if(argv[i][1] == '\0'){
flag.nfiles += argc - i - 1;
break;
}
if(strcmp(argv[i], "-m") == 0){
flag.m = TRUE;
continue;
}
if(strcmp(argv[i], "-l") == 0){
flag.l = TRUE;
flag.m = TRUE;
continue;
}
if(strcmp(argv[i], "-x") == 0){
flag.x = TRUE;
flag.m = TRUE;
continue;
}
if(strcmp(argv[i], "-arch") == 0){
if(i + 1 == argc){
error("missing argument(s) to %s option", argv[i]);
usage();
}
if(strcmp("all", argv[i+1]) == 0){
all_archs = TRUE;
}
else{
arch_flags = reallocate(arch_flags,
(narch_flags + 1) * sizeof(struct arch_flag));
if(get_arch_from_flag(argv[i+1],
arch_flags + narch_flags) == 0){
error("unknown architecture specification flag: "
"%s %s", argv[i], argv[i+1]);
arch_usage();
usage();
}
narch_flags++;
}
i++;
continue;
}
}
flag.nfiles++;
}
if(flag.m == FALSE)
printf("__TEXT\t__DATA\t__OBJC\tothers\tdec\thex\n");
args_left = TRUE;
for (i = 1; i < argc; i++) {
if(args_left == TRUE && argv[i][0] == '-'){
if(argv[i][1] == '\0'){
args_left = FALSE;
continue;
}
if(strcmp(argv[i], "-m") == 0)
continue;
if(strcmp(argv[i], "-l") == 0)
continue;
if(strcmp(argv[i], "-x") == 0)
continue;
if(strcmp(argv[i], "-arch") == 0){
i++;
continue;
}
}
ofile_process(argv[i], arch_flags, narch_flags, all_archs, FALSE,
TRUE, TRUE, size, &flag);
}
if(flag.nfiles == 0)
ofile_process("a.out", arch_flags, narch_flags, all_archs, FALSE,
TRUE, TRUE, size, &flag);
if(errors == 0)
return(EXIT_SUCCESS);
else
return(EXIT_FAILURE);
}
static
void
usage(
void)
{
fprintf(stderr, "Usage: %s [-m] [-l] [-x] [--] "
"[[-arch <arch_flag>] ...] [file ...]\n", progname);
exit(EXIT_FAILURE);
}
static
void
size(
struct ofile *ofile,
char *arch_name,
void *cookie)
{
struct flags *flag;
unsigned long seg_sum, sect_sum;
unsigned long i, j;
struct load_command *lc;
struct segment_command *sg;
struct section *s;
unsigned long text, data, objc, others, sum;
flag = (struct flags *)cookie;
if(flag->m == TRUE){
if(flag->nfiles > 1 || ofile->member_ar_hdr != NULL ||
arch_name != NULL){
if(ofile->member_ar_hdr != NULL){
printf("%s(%.*s)", ofile->file_name,
(int)ofile->member_name_size,
ofile->member_name);
}
else{
printf("%s", ofile->file_name);
}
if(arch_name != NULL)
printf(" (for architecture %s):\n", arch_name);
else
printf(":\n");
}
lc = ofile->load_commands;
seg_sum = 0;
for(i = 0; i < ofile->mh->ncmds; i++){
if(lc->cmd == LC_SEGMENT){
sg = (struct segment_command *)lc;
printf("Segment %.16s: ", sg->segname);
if(flag->x == TRUE)
printf("0x%x", (unsigned int)sg->vmsize);
else
printf("%lu", sg->vmsize);
if(sg->flags & SG_FVMLIB)
printf(" (fixed vm library segment)\n");
else{
if(flag->l == TRUE)
printf(" (vmaddr 0x%x fileoff %lu)\n",
(unsigned int)sg->vmaddr, sg->fileoff);
else
printf("\n");
}
seg_sum += sg->vmsize;
s = (struct section *)((char *)sg +
sizeof(struct segment_command));
sect_sum = 0;
for(j = 0; j < sg->nsects; j++){
if(ofile->mh->filetype == MH_OBJECT)
printf("\tSection (%.16s, %.16s): ",
s->segname, s->sectname);
else
printf("\tSection %.16s: ", s->sectname);
if(flag->x == TRUE)
printf("0x%x", (unsigned int)s->size);
else
printf("%lu", s->size);
if(flag->l == TRUE)
printf(" (addr 0x%x offset %lu)\n",
(unsigned int)s->addr, s->offset);
else
printf("\n");
sect_sum += s->size;
s++;
}
if(sg->nsects > 0){
if(flag->x == TRUE)
printf("\ttotal 0x%x\n", (unsigned int)sect_sum);
else
printf("\ttotal %lu\n", sect_sum);
}
}
lc = (struct load_command *)((char *)lc + lc->cmdsize);
}
if(flag->x == TRUE)
printf("total 0x%x\n", (unsigned int)seg_sum);
else
printf("total %lu\n", seg_sum);
}
else{
text = 0;
data = 0;
objc = 0;
others = 0;
lc = ofile->load_commands;
for(i = 0; i < ofile->mh->ncmds; i++){
if(lc->cmd == LC_SEGMENT){
sg = (struct segment_command *)lc;
if(ofile->mh->filetype == MH_OBJECT){
s = (struct section *)((char *)sg +
sizeof(struct segment_command));
for(j = 0; j < sg->nsects; j++){
if(strcmp(s->segname, SEG_TEXT) == 0)
text += s->size;
else if(strcmp(s->segname, SEG_DATA) == 0)
data += s->size;
else if(strcmp(s->segname, SEG_OBJC) == 0)
objc += s->size;
else
others += s->size;
s++;
}
}
else{
if(strcmp(sg->segname, SEG_TEXT) == 0)
text += sg->vmsize;
else if(strcmp(sg->segname, SEG_DATA) == 0)
data += sg->vmsize;
else if(strcmp(sg->segname, SEG_OBJC) == 0)
objc += sg->vmsize;
else
others += sg->vmsize;
}
}
lc = (struct load_command *)((char *)lc + lc->cmdsize);
}
printf("%lu\t%lu\t%lu\t%lu\t", text, data, objc, others);
sum = text + data + objc + others;
printf("%lu\t%x", sum, (unsigned int)sum);
if(flag->nfiles > 1 || ofile->member_ar_hdr != NULL ||
arch_name != NULL){
if(ofile->member_ar_hdr != NULL){
printf("\t%s(%.*s)", ofile->file_name,
(int)ofile->member_name_size,
ofile->member_name);
}
else{
printf("\t%s", ofile->file_name);
}
if(arch_name != NULL)
printf(" (for architecture %s)", arch_name);
}
printf("\n");
}
}