#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static sigjmp_buf jbuf; static void sigill_handler(int sig){ (void)sig; siglongjmp(jbuf,1); } static double now_sec(void){ struct timespec ts; clock_gettime(CLOCK_MONOTONIC,&ts); return ts.tv_sec+ts.tv_nsec/1e9; } static uint32_t crc32_tab[256]; static void crc32_init(void){ for(uint32_t i=0;i<256;i++){ uint32_t c=i; for(int j=0;j<8;j++) c = (c&1)?(0xEDB88320^(c>>1)):(c>>1); crc32_tab[i]=c; } } static uint32_t crc32_calc(uint8_t *buf,size_t len){ uint32_t c=0xFFFFFFFF; for(size_t i=0;i>8); return c^0xFFFFFFFF; } static void analyze_header(uint8_t *data,size_t sz){ printf("=== Magic Header / Instruction Analysis ===\n"); if(sz<4){ printf("File too small\n"); return; } printf("First 16 bytes: "); for(int i=0;i<16 && i<(int)sz;i++) printf("%02X ",data[i]); printf("\n"); if(sz>4 && data[0]==0x7F && data[1]=='E' && data[2]=='L' && data[3]=='F'){ int ei_class=data[4]; int ei_data=data[5]; printf("Format: ELF\n"); printf("Class: %s\n", ei_class==1?"32-bit":ei_class==2?"64-bit":"Unknown"); printf("Endianness: %s\n", ei_data==1?"Little Endian":ei_data==2?"Big Endian":"Unknown"); uint16_t machine; memcpy(&machine,data+18,2); printf("Machine field: 0x%04X\n", machine); } else { uint32_t magic_le, magic_be; memcpy(&magic_le,data,4); magic_be = __builtin_bswap32(magic_le); printf("Raw magic LE: 0x%08X\n", magic_le); printf("Raw magic BE: 0x%08X\n", magic_be); if(magic_be==0x27051956) printf("Detected: Legacy U-Boot image header\n"); else printf("Format: Raw binary (no standard header detected)\n"); int lecount=0, becount=0; for(size_t i=0;i+4<=sz && i<4096;i+=4){ uint32_t w; memcpy(&w,data+i,4); if((w & 0xFF000000)==0 && (w&0xFF)!=0) lecount++; else if((w & 0xFF)==0 && (w&0xFF000000)!=0) becount++; } printf("Heuristic endianness guess: %s\n", lecount>=becount?"Little Endian likely":"Big Endian likely"); } printf("\n"); } static void analyze_cache(void){ printf("=== Cache Availability ===\n"); long l1d = sysconf(_SC_LEVEL1_DCACHE_SIZE); long l1i = sysconf(_SC_LEVEL1_ICACHE_SIZE); long l2 = sysconf(_SC_LEVEL2_CACHE_SIZE); long l3 = sysconf(_SC_LEVEL3_CACHE_SIZE); printf("L1D: %ld bytes\n", l1d>0?l1d:0); printf("L1I: %ld bytes\n", l1i>0?l1i:0); printf("L2 : %ld bytes\n", l2>0?l2:0); printf("L3 : %ld bytes\n", l3>0?l3:0); size_t bufsz = 1<<20; uint8_t *buf = malloc(bufsz); memset(buf,0xAA,bufsz); volatile uint64_t sum=0; double t0=now_sec(); for(int r=0;r<50;r++) for(size_t i=0;i>2)&3); unsigned long tcr = safe_read_sysreg("tcr_el1"); if(tcr==(unsigned long)-1) printf("TCR_EL1: unreadable from EL0 (trapped, expected in userspace)\n"); else{ printf("TCR_EL1 raw value: 0x%lx\n", tcr); int tbi_enabled = (tcr>>37)&1; printf("Top-Byte-Ignore (pointer tagging) TBI0: %s\n", tbi_enabled?"Enabled":"Disabled/Unknown"); } unsigned long id_aa64pfr1 = safe_read_sysreg("id_aa64pfr1_el1"); if(id_aa64pfr1==(unsigned long)-1) printf("ID_AA64PFR1_EL1: unreadable from EL0 (trapped)\n"); else{ int mte = (id_aa64pfr1>>8)&0xF; printf("MTE support level: %d (%s)\n", mte, mte>0?"Supported":"Not supported"); } #else printf("Non-AArch64 host: pointer tagging/MTE/EL registers not applicable\n"); #endif printf("\n"); } static void analyze_eof(uint8_t *data,size_t sz){ printf("=== End of File Signature ===\n"); if(sz<16){ printf("File too small\n\n"); return; } printf("Last 16 bytes: "); for(size_t i=sz-16;i=minlen){ printf("0x%08zx: %.*s\n", start,(int)len,data+start); count++; } i++; } printf("\n"); } static void analyze_size(const char *path){ printf("=== File Size ===\n"); struct stat st; if(stat(path,&st)==0){ printf("Physical size: %lld bytes\n",(long long)st.st_size); printf("Size on disk : %lld bytes (blocks: %lld x 512)\n", (long long)st.st_blocks*512,(long long)st.st_blocks); } printf("\n"); } static void analyze_integrity(uint8_t *data,size_t sz){ printf("=== Integrity Checksum (CRC32) ===\n"); crc32_init(); uint32_t c = crc32_calc(data,sz); printf("CRC32: 0x%08X\n", c); printf("\n"); } int main(int argc,char **argv){ if(argc<2){ fprintf(stderr,"Usage: %s \n",argv[0]); return 1; } const char *path = argv[1]; int fd = open(path,O_RDONLY); if(fd<0){ perror("open"); return 1; } struct stat st; fstat(fd,&st); size_t sz = st.st_size; uint8_t *data = mmap(NULL,sz,PROT_READ,MAP_PRIVATE,fd,0); if(data==MAP_FAILED){ perror("mmap"); close(fd); return 1; } printf("Baremetal Profile Report: %s\n\n", path); analyze_header(data,sz); analyze_cache(); analyze_ram(); analyze_disk(path,sz); analyze_security(); analyze_eof(data,sz); analyze_network(); analyze_strings(data,sz); analyze_size(path); analyze_integrity(data,sz); munmap(data,sz); close(fd); return 0; }