1*402d77f6SIngo Weinhold /* 2*402d77f6SIngo Weinhold * Copyright 2007, Ingo Weinhold <bonefish@cs.tu-berlin.de>. 3*402d77f6SIngo Weinhold * All rights reserved. Distributed under the terms of the MIT License. 4*402d77f6SIngo Weinhold */ 5*402d77f6SIngo Weinhold 6*402d77f6SIngo Weinhold #include <errno.h> 7*402d77f6SIngo Weinhold #include <fcntl.h> 8*402d77f6SIngo Weinhold #include <inttypes.h> 9*402d77f6SIngo Weinhold #include <stdarg.h> 10*402d77f6SIngo Weinhold #include <stdio.h> 11*402d77f6SIngo Weinhold #include <stdlib.h> 12*402d77f6SIngo Weinhold #include <unistd.h> 13*402d77f6SIngo Weinhold 14*402d77f6SIngo Weinhold #include <algorithm> 15*402d77f6SIngo Weinhold #include <string> 16*402d77f6SIngo Weinhold 17*402d77f6SIngo Weinhold #include <arpa/inet.h> 18*402d77f6SIngo Weinhold 19*402d77f6SIngo Weinhold 20*402d77f6SIngo Weinhold using std::string; 21*402d77f6SIngo Weinhold using std::max; 22*402d77f6SIngo Weinhold using std::min; 23*402d77f6SIngo Weinhold 24*402d77f6SIngo Weinhold 25*402d77f6SIngo Weinhold // #pragma mark - ELF definitions 26*402d77f6SIngo Weinhold 27*402d77f6SIngo Weinhold 28*402d77f6SIngo Weinhold // types 29*402d77f6SIngo Weinhold typedef uint32_t Elf32_Addr; 30*402d77f6SIngo Weinhold typedef uint16_t Elf32_Half; 31*402d77f6SIngo Weinhold typedef uint32_t Elf32_Off; 32*402d77f6SIngo Weinhold typedef int32_t Elf32_Sword; 33*402d77f6SIngo Weinhold typedef uint32_t Elf32_Word; 34*402d77f6SIngo Weinhold 35*402d77f6SIngo Weinhold // e_ident indices 36*402d77f6SIngo Weinhold #define EI_MAG0 0 37*402d77f6SIngo Weinhold #define EI_MAG1 1 38*402d77f6SIngo Weinhold #define EI_MAG2 2 39*402d77f6SIngo Weinhold #define EI_MAG3 3 40*402d77f6SIngo Weinhold #define EI_CLASS 4 41*402d77f6SIngo Weinhold #define EI_DATA 5 42*402d77f6SIngo Weinhold #define EI_VERSION 6 43*402d77f6SIngo Weinhold #define EI_PAD 7 44*402d77f6SIngo Weinhold #define EI_NIDENT 16 45*402d77f6SIngo Weinhold 46*402d77f6SIngo Weinhold // object file header 47*402d77f6SIngo Weinhold typedef struct { 48*402d77f6SIngo Weinhold unsigned char e_ident[EI_NIDENT]; 49*402d77f6SIngo Weinhold Elf32_Half e_type; 50*402d77f6SIngo Weinhold Elf32_Half e_machine; 51*402d77f6SIngo Weinhold Elf32_Word e_version; 52*402d77f6SIngo Weinhold Elf32_Addr e_entry; 53*402d77f6SIngo Weinhold Elf32_Off e_phoff; 54*402d77f6SIngo Weinhold Elf32_Off e_shoff; 55*402d77f6SIngo Weinhold Elf32_Word e_flags; 56*402d77f6SIngo Weinhold Elf32_Half e_ehsize; 57*402d77f6SIngo Weinhold Elf32_Half e_phentsize; 58*402d77f6SIngo Weinhold Elf32_Half e_phnum; 59*402d77f6SIngo Weinhold Elf32_Half e_shentsize; 60*402d77f6SIngo Weinhold Elf32_Half e_shnum; 61*402d77f6SIngo Weinhold Elf32_Half e_shstrndx; 62*402d77f6SIngo Weinhold } Elf32_Ehdr; 63*402d77f6SIngo Weinhold 64*402d77f6SIngo Weinhold // e_ident EI_CLASS and EI_DATA values 65*402d77f6SIngo Weinhold #define ELFCLASSNONE 0 66*402d77f6SIngo Weinhold #define ELFCLASS32 1 67*402d77f6SIngo Weinhold #define ELFCLASS64 2 68*402d77f6SIngo Weinhold #define ELFDATANONE 0 69*402d77f6SIngo Weinhold #define ELFDATA2LSB 1 70*402d77f6SIngo Weinhold #define ELFDATA2MSB 2 71*402d77f6SIngo Weinhold 72*402d77f6SIngo Weinhold // program header 73*402d77f6SIngo Weinhold typedef struct { 74*402d77f6SIngo Weinhold Elf32_Word p_type; 75*402d77f6SIngo Weinhold Elf32_Off p_offset; 76*402d77f6SIngo Weinhold Elf32_Addr p_vaddr; 77*402d77f6SIngo Weinhold Elf32_Addr p_paddr; 78*402d77f6SIngo Weinhold Elf32_Word p_filesz; 79*402d77f6SIngo Weinhold Elf32_Word p_memsz; 80*402d77f6SIngo Weinhold Elf32_Word p_flags; 81*402d77f6SIngo Weinhold Elf32_Word p_align; 82*402d77f6SIngo Weinhold } Elf32_Phdr; 83*402d77f6SIngo Weinhold 84*402d77f6SIngo Weinhold // p_type 85*402d77f6SIngo Weinhold #define PT_NULL 0 86*402d77f6SIngo Weinhold #define PT_LOAD 1 87*402d77f6SIngo Weinhold #define PT_DYNAMIC 2 88*402d77f6SIngo Weinhold #define PT_INTERP 3 89*402d77f6SIngo Weinhold #define PT_NOTE 4 90*402d77f6SIngo Weinhold #define PT_SHLIB 5 91*402d77f6SIngo Weinhold #define PT_PHDIR 6 92*402d77f6SIngo Weinhold #define PT_LOPROC 0x70000000 93*402d77f6SIngo Weinhold #define PT_HIPROC 0x7fffffff 94*402d77f6SIngo Weinhold 95*402d77f6SIngo Weinhold // section header 96*402d77f6SIngo Weinhold typedef struct { 97*402d77f6SIngo Weinhold Elf32_Word sh_name; 98*402d77f6SIngo Weinhold Elf32_Word sh_type; 99*402d77f6SIngo Weinhold Elf32_Word sh_flags; 100*402d77f6SIngo Weinhold Elf32_Addr sh_addr; 101*402d77f6SIngo Weinhold Elf32_Off sh_offset; 102*402d77f6SIngo Weinhold Elf32_Word sh_size; 103*402d77f6SIngo Weinhold Elf32_Word sh_link; 104*402d77f6SIngo Weinhold Elf32_Word sh_info; 105*402d77f6SIngo Weinhold Elf32_Word sh_addralign; 106*402d77f6SIngo Weinhold Elf32_Word sh_entsize; 107*402d77f6SIngo Weinhold } Elf32_Shdr; 108*402d77f6SIngo Weinhold 109*402d77f6SIngo Weinhold // sh_type values 110*402d77f6SIngo Weinhold #define SHT_NULL 0 111*402d77f6SIngo Weinhold #define SHT_PROGBITS 1 112*402d77f6SIngo Weinhold #define SHT_SYMTAB 2 113*402d77f6SIngo Weinhold #define SHT_STRTAB 3 114*402d77f6SIngo Weinhold #define SHT_RELA 4 115*402d77f6SIngo Weinhold #define SHT_HASH 5 116*402d77f6SIngo Weinhold #define SHT_DYNAMIC 6 117*402d77f6SIngo Weinhold #define SHT_NOTE 7 118*402d77f6SIngo Weinhold #define SHT_NOBITS 8 119*402d77f6SIngo Weinhold #define SHT_REL 9 120*402d77f6SIngo Weinhold #define SHT_SHLIB 10 121*402d77f6SIngo Weinhold #define SHT_DYNSYM 11 122*402d77f6SIngo Weinhold #define SHT_LOPROC 0x70000000 123*402d77f6SIngo Weinhold #define SHT_HIPROC 0x7fffffff 124*402d77f6SIngo Weinhold #define SHT_LOUSER 0x80000000 125*402d77f6SIngo Weinhold #define SHT_HIUSER 0xffffffff 126*402d77f6SIngo Weinhold 127*402d77f6SIngo Weinhold // special section indexes 128*402d77f6SIngo Weinhold #define SHN_UNDEF 0 129*402d77f6SIngo Weinhold 130*402d77f6SIngo Weinhold static const uint32_t kMaxELFHeaderSize = sizeof(Elf32_Ehdr) + 32; 131*402d77f6SIngo Weinhold static const char kELFFileMagic[4] = { 0x7f, 'E', 'L', 'F' }; 132*402d77f6SIngo Weinhold 133*402d77f6SIngo Weinhold 134*402d77f6SIngo Weinhold // #pragma mark - Usage 135*402d77f6SIngo Weinhold 136*402d77f6SIngo Weinhold // usage 137*402d77f6SIngo Weinhold static const char *kUsage = 138*402d77f6SIngo Weinhold "Usage: %s <file> <revision>\n" 139*402d77f6SIngo Weinhold "\n" 140*402d77f6SIngo Weinhold "Finds the haiku revision section in ELF object file <file> and replaces the\n" 141*402d77f6SIngo Weinhold "writes the number given by <revision> into the first 32 bits of the\n" 142*402d77f6SIngo Weinhold "section.\n" 143*402d77f6SIngo Weinhold ; 144*402d77f6SIngo Weinhold 145*402d77f6SIngo Weinhold // command line args 146*402d77f6SIngo Weinhold static int sArgc; 147*402d77f6SIngo Weinhold static const char *const *sArgv; 148*402d77f6SIngo Weinhold 149*402d77f6SIngo Weinhold // print_usage 150*402d77f6SIngo Weinhold void 151*402d77f6SIngo Weinhold print_usage(bool error) 152*402d77f6SIngo Weinhold { 153*402d77f6SIngo Weinhold // get nice program name 154*402d77f6SIngo Weinhold const char *programName = (sArgc > 0 ? sArgv[0] : "resattr"); 155*402d77f6SIngo Weinhold if (const char *lastSlash = strrchr(programName, '/')) 156*402d77f6SIngo Weinhold programName = lastSlash + 1; 157*402d77f6SIngo Weinhold 158*402d77f6SIngo Weinhold // print usage 159*402d77f6SIngo Weinhold fprintf((error ? stderr : stdout), kUsage, programName); 160*402d77f6SIngo Weinhold } 161*402d77f6SIngo Weinhold 162*402d77f6SIngo Weinhold // print_usage_and_exit 163*402d77f6SIngo Weinhold static 164*402d77f6SIngo Weinhold void 165*402d77f6SIngo Weinhold print_usage_and_exit(bool error) 166*402d77f6SIngo Weinhold { 167*402d77f6SIngo Weinhold print_usage(error); 168*402d77f6SIngo Weinhold exit(error ? 1 : 0); 169*402d77f6SIngo Weinhold } 170*402d77f6SIngo Weinhold 171*402d77f6SIngo Weinhold 172*402d77f6SIngo Weinhold // #pragma mark - Exception 173*402d77f6SIngo Weinhold 174*402d77f6SIngo Weinhold 175*402d77f6SIngo Weinhold class Exception { 176*402d77f6SIngo Weinhold public: 177*402d77f6SIngo Weinhold // constructor 178*402d77f6SIngo Weinhold Exception() 179*402d77f6SIngo Weinhold : fError(errno), 180*402d77f6SIngo Weinhold fDescription() 181*402d77f6SIngo Weinhold { 182*402d77f6SIngo Weinhold } 183*402d77f6SIngo Weinhold 184*402d77f6SIngo Weinhold // constructor 185*402d77f6SIngo Weinhold Exception(const char* format,...) 186*402d77f6SIngo Weinhold : fError(errno), 187*402d77f6SIngo Weinhold fDescription() 188*402d77f6SIngo Weinhold { 189*402d77f6SIngo Weinhold va_list args; 190*402d77f6SIngo Weinhold va_start(args, format); 191*402d77f6SIngo Weinhold SetTo(errno, format, args); 192*402d77f6SIngo Weinhold va_end(args); 193*402d77f6SIngo Weinhold } 194*402d77f6SIngo Weinhold 195*402d77f6SIngo Weinhold // constructor 196*402d77f6SIngo Weinhold Exception(int error) 197*402d77f6SIngo Weinhold : fError(error), 198*402d77f6SIngo Weinhold fDescription() 199*402d77f6SIngo Weinhold { 200*402d77f6SIngo Weinhold } 201*402d77f6SIngo Weinhold 202*402d77f6SIngo Weinhold // constructor 203*402d77f6SIngo Weinhold Exception(int error, const char* format,...) 204*402d77f6SIngo Weinhold : fError(error), 205*402d77f6SIngo Weinhold fDescription() 206*402d77f6SIngo Weinhold { 207*402d77f6SIngo Weinhold va_list args; 208*402d77f6SIngo Weinhold va_start(args, format); 209*402d77f6SIngo Weinhold SetTo(error, format, args); 210*402d77f6SIngo Weinhold va_end(args); 211*402d77f6SIngo Weinhold } 212*402d77f6SIngo Weinhold 213*402d77f6SIngo Weinhold // copy constructor 214*402d77f6SIngo Weinhold Exception(const Exception& exception) 215*402d77f6SIngo Weinhold : fError(exception.fError), 216*402d77f6SIngo Weinhold fDescription(exception.fDescription) 217*402d77f6SIngo Weinhold { 218*402d77f6SIngo Weinhold } 219*402d77f6SIngo Weinhold 220*402d77f6SIngo Weinhold // destructor 221*402d77f6SIngo Weinhold ~Exception() 222*402d77f6SIngo Weinhold { 223*402d77f6SIngo Weinhold } 224*402d77f6SIngo Weinhold 225*402d77f6SIngo Weinhold // SetTo 226*402d77f6SIngo Weinhold void SetTo(int error, const char* format, va_list arg) 227*402d77f6SIngo Weinhold { 228*402d77f6SIngo Weinhold char buffer[2048]; 229*402d77f6SIngo Weinhold vsprintf(buffer, format, arg); 230*402d77f6SIngo Weinhold fError = error; 231*402d77f6SIngo Weinhold fDescription = buffer; 232*402d77f6SIngo Weinhold } 233*402d77f6SIngo Weinhold 234*402d77f6SIngo Weinhold // Error 235*402d77f6SIngo Weinhold int Error() const 236*402d77f6SIngo Weinhold { 237*402d77f6SIngo Weinhold return fError; 238*402d77f6SIngo Weinhold } 239*402d77f6SIngo Weinhold 240*402d77f6SIngo Weinhold // Description 241*402d77f6SIngo Weinhold const string& Description() const 242*402d77f6SIngo Weinhold { 243*402d77f6SIngo Weinhold return fDescription; 244*402d77f6SIngo Weinhold } 245*402d77f6SIngo Weinhold 246*402d77f6SIngo Weinhold private: 247*402d77f6SIngo Weinhold int fError; 248*402d77f6SIngo Weinhold string fDescription; 249*402d77f6SIngo Weinhold }; 250*402d77f6SIngo Weinhold 251*402d77f6SIngo Weinhold 252*402d77f6SIngo Weinhold // #pragma mark - ELFObject 253*402d77f6SIngo Weinhold 254*402d77f6SIngo Weinhold 255*402d77f6SIngo Weinhold struct SectionInfo { 256*402d77f6SIngo Weinhold uint32_t type; 257*402d77f6SIngo Weinhold uint32_t offset; 258*402d77f6SIngo Weinhold uint32_t size; 259*402d77f6SIngo Weinhold const char* name; 260*402d77f6SIngo Weinhold }; 261*402d77f6SIngo Weinhold 262*402d77f6SIngo Weinhold 263*402d77f6SIngo Weinhold class ELFObject { 264*402d77f6SIngo Weinhold public: 265*402d77f6SIngo Weinhold ELFObject() 266*402d77f6SIngo Weinhold : fFD(-1), 267*402d77f6SIngo Weinhold fSectionHeaderStrings(NULL), 268*402d77f6SIngo Weinhold fSectionHeaderStringsLength(0) 269*402d77f6SIngo Weinhold { 270*402d77f6SIngo Weinhold } 271*402d77f6SIngo Weinhold 272*402d77f6SIngo Weinhold ~ELFObject() 273*402d77f6SIngo Weinhold { 274*402d77f6SIngo Weinhold Unset(); 275*402d77f6SIngo Weinhold } 276*402d77f6SIngo Weinhold 277*402d77f6SIngo Weinhold void Unset() 278*402d77f6SIngo Weinhold { 279*402d77f6SIngo Weinhold if (fFD >= 0) { 280*402d77f6SIngo Weinhold close(fFD); 281*402d77f6SIngo Weinhold fFD = -1; 282*402d77f6SIngo Weinhold } 283*402d77f6SIngo Weinhold 284*402d77f6SIngo Weinhold delete[] fSectionHeaderStrings; 285*402d77f6SIngo Weinhold fSectionHeaderStrings = NULL; 286*402d77f6SIngo Weinhold } 287*402d77f6SIngo Weinhold 288*402d77f6SIngo Weinhold void SetTo(const char* fileName) 289*402d77f6SIngo Weinhold { 290*402d77f6SIngo Weinhold Unset(); 291*402d77f6SIngo Weinhold 292*402d77f6SIngo Weinhold // open the file 293*402d77f6SIngo Weinhold fFD = open(fileName, O_RDWR); 294*402d77f6SIngo Weinhold if (fFD < 0) 295*402d77f6SIngo Weinhold throw Exception("Failed to open \"%s\"", fileName); 296*402d77f6SIngo Weinhold 297*402d77f6SIngo Weinhold // get the file size 298*402d77f6SIngo Weinhold fFileSize = FileSize(); 299*402d77f6SIngo Weinhold if (fFileSize < 0) 300*402d77f6SIngo Weinhold throw Exception("Failed to get the file size."); 301*402d77f6SIngo Weinhold 302*402d77f6SIngo Weinhold // read ELF header 303*402d77f6SIngo Weinhold Elf32_Ehdr fileHeader; 304*402d77f6SIngo Weinhold Read(0, &fileHeader, sizeof(Elf32_Ehdr), "Failed to read ELF header."); 305*402d77f6SIngo Weinhold 306*402d77f6SIngo Weinhold // check data encoding (endianess) 307*402d77f6SIngo Weinhold switch (fileHeader.e_ident[EI_DATA]) { 308*402d77f6SIngo Weinhold case ELFDATA2LSB: 309*402d77f6SIngo Weinhold fHostEndianess = (htonl(1) != 1); 310*402d77f6SIngo Weinhold break; 311*402d77f6SIngo Weinhold case ELFDATA2MSB: 312*402d77f6SIngo Weinhold fHostEndianess = (htonl(1) == 1); 313*402d77f6SIngo Weinhold break; 314*402d77f6SIngo Weinhold default: 315*402d77f6SIngo Weinhold case ELFDATANONE: 316*402d77f6SIngo Weinhold throw Exception(EIO, "Unsupported ELF data encoding."); 317*402d77f6SIngo Weinhold break; 318*402d77f6SIngo Weinhold } 319*402d77f6SIngo Weinhold 320*402d77f6SIngo Weinhold // get the header values 321*402d77f6SIngo Weinhold fELFHeaderSize = GetUInt16(fileHeader.e_ehsize); 322*402d77f6SIngo Weinhold fSectionHeaderTableOffset = GetUInt32(fileHeader.e_shoff); 323*402d77f6SIngo Weinhold fSectionHeaderSize = GetUInt16(fileHeader.e_shentsize); 324*402d77f6SIngo Weinhold fSectionHeaderCount = GetUInt16(fileHeader.e_shnum); 325*402d77f6SIngo Weinhold bool hasSectionHeaderTable = (fSectionHeaderTableOffset != 0); 326*402d77f6SIngo Weinhold 327*402d77f6SIngo Weinhold // check the sanity of the header values 328*402d77f6SIngo Weinhold // ELF header size 329*402d77f6SIngo Weinhold if (fELFHeaderSize < sizeof(Elf32_Ehdr) || fELFHeaderSize > kMaxELFHeaderSize) { 330*402d77f6SIngo Weinhold throw Exception(EIO, 331*402d77f6SIngo Weinhold "Invalid ELF header: invalid ELF header size: %lu.", 332*402d77f6SIngo Weinhold fELFHeaderSize); 333*402d77f6SIngo Weinhold } 334*402d77f6SIngo Weinhold 335*402d77f6SIngo Weinhold // section header table offset and entry count/size 336*402d77f6SIngo Weinhold uint32_t sectionHeaderTableSize = 0; 337*402d77f6SIngo Weinhold if (hasSectionHeaderTable) { 338*402d77f6SIngo Weinhold if (fSectionHeaderTableOffset < fELFHeaderSize 339*402d77f6SIngo Weinhold || fSectionHeaderTableOffset > fFileSize) { 340*402d77f6SIngo Weinhold throw Exception(EIO, "Invalid ELF header: invalid section " 341*402d77f6SIngo Weinhold "header table offset: %lu.", 342*402d77f6SIngo Weinhold fSectionHeaderTableOffset); 343*402d77f6SIngo Weinhold } 344*402d77f6SIngo Weinhold sectionHeaderTableSize = fSectionHeaderSize * fSectionHeaderCount; 345*402d77f6SIngo Weinhold if (fSectionHeaderSize < sizeof(Elf32_Shdr) 346*402d77f6SIngo Weinhold || fSectionHeaderTableOffset + sectionHeaderTableSize 347*402d77f6SIngo Weinhold > fFileSize) { 348*402d77f6SIngo Weinhold throw Exception(EIO, "Invalid ELF header: section header " 349*402d77f6SIngo Weinhold "table exceeds file: %lu.", 350*402d77f6SIngo Weinhold fSectionHeaderTableOffset 351*402d77f6SIngo Weinhold + sectionHeaderTableSize); 352*402d77f6SIngo Weinhold } 353*402d77f6SIngo Weinhold 354*402d77f6SIngo Weinhold 355*402d77f6SIngo Weinhold // load section header string section 356*402d77f6SIngo Weinhold uint16_t sectionHeaderStringSectionIndex 357*402d77f6SIngo Weinhold = GetUInt16(fileHeader.e_shstrndx); 358*402d77f6SIngo Weinhold if (sectionHeaderStringSectionIndex != SHN_UNDEF) { 359*402d77f6SIngo Weinhold if (sectionHeaderStringSectionIndex >= fSectionHeaderCount) { 360*402d77f6SIngo Weinhold throw Exception(EIO, "Invalid ELF header: invalid section " 361*402d77f6SIngo Weinhold "header string section index: %lu.", 362*402d77f6SIngo Weinhold sectionHeaderStringSectionIndex); 363*402d77f6SIngo Weinhold } 364*402d77f6SIngo Weinhold 365*402d77f6SIngo Weinhold // get the section info 366*402d77f6SIngo Weinhold SectionInfo info; 367*402d77f6SIngo Weinhold if (_ReadSectionHeader(sectionHeaderStringSectionIndex, 368*402d77f6SIngo Weinhold info)) { 369*402d77f6SIngo Weinhold fSectionHeaderStrings = new char[info.size + 1]; 370*402d77f6SIngo Weinhold Read(info.offset, fSectionHeaderStrings, info.size, 371*402d77f6SIngo Weinhold "Failed to read section header string section."); 372*402d77f6SIngo Weinhold fSectionHeaderStringsLength = info.size; 373*402d77f6SIngo Weinhold // null-terminate to be on the safe side 374*402d77f6SIngo Weinhold fSectionHeaderStrings[info.size] = '\0'; 375*402d77f6SIngo Weinhold } 376*402d77f6SIngo Weinhold } 377*402d77f6SIngo Weinhold } 378*402d77f6SIngo Weinhold } 379*402d77f6SIngo Weinhold 380*402d77f6SIngo Weinhold bool FindSectionByName(const char* name, SectionInfo& foundInfo) 381*402d77f6SIngo Weinhold { 382*402d77f6SIngo Weinhold // can't find the section by name without section names 383*402d77f6SIngo Weinhold if (!fSectionHeaderStrings) 384*402d77f6SIngo Weinhold return false; 385*402d77f6SIngo Weinhold 386*402d77f6SIngo Weinhold // iterate through the section headers 387*402d77f6SIngo Weinhold for (int32_t i = 0; i < (int32_t)fSectionHeaderCount; i++) { 388*402d77f6SIngo Weinhold SectionInfo info; 389*402d77f6SIngo Weinhold if (_ReadSectionHeader(i, info)) { 390*402d77f6SIngo Weinhold //printf("section %3d: offset: %7d, size: %7d, name: %s\n", i, info.offset, info.size, info.name); 391*402d77f6SIngo Weinhold if (strcmp(info.name, name) == 0) { 392*402d77f6SIngo Weinhold foundInfo = info; 393*402d77f6SIngo Weinhold return true; 394*402d77f6SIngo Weinhold } 395*402d77f6SIngo Weinhold } 396*402d77f6SIngo Weinhold } 397*402d77f6SIngo Weinhold 398*402d77f6SIngo Weinhold return false; 399*402d77f6SIngo Weinhold } 400*402d77f6SIngo Weinhold 401*402d77f6SIngo Weinhold void Read(off_t position, void* buffer, size_t size, 402*402d77f6SIngo Weinhold const char *errorMessage = NULL) 403*402d77f6SIngo Weinhold { 404*402d77f6SIngo Weinhold if (lseek(fFD, position, SEEK_SET) < 0) 405*402d77f6SIngo Weinhold throw Exception(errorMessage); 406*402d77f6SIngo Weinhold 407*402d77f6SIngo Weinhold ssize_t bytesRead = read(fFD, buffer, size); 408*402d77f6SIngo Weinhold if (bytesRead < 0) 409*402d77f6SIngo Weinhold throw Exception(errorMessage); 410*402d77f6SIngo Weinhold 411*402d77f6SIngo Weinhold if ((size_t)bytesRead != size) { 412*402d77f6SIngo Weinhold if (errorMessage) { 413*402d77f6SIngo Weinhold throw Exception("%s Read too few bytes (%d/%d).", 414*402d77f6SIngo Weinhold errorMessage, (int)bytesRead, (int)size); 415*402d77f6SIngo Weinhold } else { 416*402d77f6SIngo Weinhold throw Exception("Read too few bytes (%ld/%lu).", 417*402d77f6SIngo Weinhold (int)bytesRead, (int)size); 418*402d77f6SIngo Weinhold } 419*402d77f6SIngo Weinhold } 420*402d77f6SIngo Weinhold } 421*402d77f6SIngo Weinhold 422*402d77f6SIngo Weinhold void Write(off_t position, const void* buffer, size_t size, 423*402d77f6SIngo Weinhold const char *errorMessage = NULL) 424*402d77f6SIngo Weinhold { 425*402d77f6SIngo Weinhold if (lseek(fFD, position, SEEK_SET) < 0) 426*402d77f6SIngo Weinhold throw Exception(errorMessage); 427*402d77f6SIngo Weinhold 428*402d77f6SIngo Weinhold ssize_t bytesWritten = write(fFD, buffer, size); 429*402d77f6SIngo Weinhold if (bytesWritten < 0) 430*402d77f6SIngo Weinhold throw Exception(errorMessage); 431*402d77f6SIngo Weinhold 432*402d77f6SIngo Weinhold if ((size_t)bytesWritten != size) { 433*402d77f6SIngo Weinhold if (errorMessage) { 434*402d77f6SIngo Weinhold throw Exception("%s Wrote too few bytes (%d/%d).", 435*402d77f6SIngo Weinhold errorMessage, (int)bytesWritten, (int)size); 436*402d77f6SIngo Weinhold } else { 437*402d77f6SIngo Weinhold throw Exception("Wrote too few bytes (%ld/%lu).", 438*402d77f6SIngo Weinhold (int)bytesWritten, (int)size); 439*402d77f6SIngo Weinhold } 440*402d77f6SIngo Weinhold } 441*402d77f6SIngo Weinhold } 442*402d77f6SIngo Weinhold 443*402d77f6SIngo Weinhold off_t FileSize() 444*402d77f6SIngo Weinhold { 445*402d77f6SIngo Weinhold off_t currentPos = lseek(fFD, 0, SEEK_END); 446*402d77f6SIngo Weinhold if (currentPos < 0) 447*402d77f6SIngo Weinhold return -1; 448*402d77f6SIngo Weinhold 449*402d77f6SIngo Weinhold return lseek(fFD, currentPos, SEEK_SET); 450*402d77f6SIngo Weinhold } 451*402d77f6SIngo Weinhold 452*402d77f6SIngo Weinhold // GetInt16 453*402d77f6SIngo Weinhold int16_t GetInt16(int16_t value) 454*402d77f6SIngo Weinhold { 455*402d77f6SIngo Weinhold return (fHostEndianess ? value : _SwapUInt16(value)); 456*402d77f6SIngo Weinhold } 457*402d77f6SIngo Weinhold 458*402d77f6SIngo Weinhold // GetUInt16 459*402d77f6SIngo Weinhold uint16_t GetUInt16(uint16_t value) 460*402d77f6SIngo Weinhold { 461*402d77f6SIngo Weinhold return (fHostEndianess ? value : _SwapUInt16(value)); 462*402d77f6SIngo Weinhold } 463*402d77f6SIngo Weinhold 464*402d77f6SIngo Weinhold // GetInt32 465*402d77f6SIngo Weinhold int32_t GetInt32(int32_t value) 466*402d77f6SIngo Weinhold { 467*402d77f6SIngo Weinhold return (fHostEndianess ? value : _SwapUInt32(value)); 468*402d77f6SIngo Weinhold } 469*402d77f6SIngo Weinhold 470*402d77f6SIngo Weinhold // GetUInt32 471*402d77f6SIngo Weinhold uint32_t GetUInt32(uint32_t value) 472*402d77f6SIngo Weinhold { 473*402d77f6SIngo Weinhold return (fHostEndianess ? value : _SwapUInt32(value)); 474*402d77f6SIngo Weinhold } 475*402d77f6SIngo Weinhold 476*402d77f6SIngo Weinhold private: 477*402d77f6SIngo Weinhold bool _ReadSectionHeader(int index, SectionInfo& info) 478*402d77f6SIngo Weinhold { 479*402d77f6SIngo Weinhold uint32_t shOffset = fSectionHeaderTableOffset 480*402d77f6SIngo Weinhold + index * fSectionHeaderSize; 481*402d77f6SIngo Weinhold Elf32_Shdr sectionHeader; 482*402d77f6SIngo Weinhold Read(shOffset, §ionHeader, sizeof(Elf32_Shdr), 483*402d77f6SIngo Weinhold "Failed to read ELF section header."); 484*402d77f6SIngo Weinhold 485*402d77f6SIngo Weinhold // get the header values 486*402d77f6SIngo Weinhold uint32_t type = GetUInt32(sectionHeader.sh_type); 487*402d77f6SIngo Weinhold uint32_t offset = GetUInt32(sectionHeader.sh_offset); 488*402d77f6SIngo Weinhold uint32_t size = GetUInt32(sectionHeader.sh_size); 489*402d77f6SIngo Weinhold uint32_t nameIndex = GetUInt32(sectionHeader.sh_name); 490*402d77f6SIngo Weinhold 491*402d77f6SIngo Weinhold // check the values 492*402d77f6SIngo Weinhold // SHT_NULL marks the header unused, 493*402d77f6SIngo Weinhold if (type == SHT_NULL) 494*402d77f6SIngo Weinhold return false; 495*402d77f6SIngo Weinhold 496*402d77f6SIngo Weinhold // SHT_NOBITS sections take no space in the file 497*402d77f6SIngo Weinhold if (type != SHT_NOBITS) { 498*402d77f6SIngo Weinhold if (offset < fELFHeaderSize || offset > fFileSize) { 499*402d77f6SIngo Weinhold throw Exception(EIO, "Invalid ELF section header: " 500*402d77f6SIngo Weinhold "invalid section offset: %lu.", offset); 501*402d77f6SIngo Weinhold } 502*402d77f6SIngo Weinhold uint32_t sectionEnd = offset + size; 503*402d77f6SIngo Weinhold if (sectionEnd > fFileSize) { 504*402d77f6SIngo Weinhold throw Exception(EIO, "Invalid ELF section header: " 505*402d77f6SIngo Weinhold "section exceeds file: %lu.", sectionEnd); 506*402d77f6SIngo Weinhold } 507*402d77f6SIngo Weinhold } 508*402d77f6SIngo Weinhold 509*402d77f6SIngo Weinhold // get name, if we have a string section 510*402d77f6SIngo Weinhold if (fSectionHeaderStrings) { 511*402d77f6SIngo Weinhold if (nameIndex >= (uint32_t)fSectionHeaderStringsLength) { 512*402d77f6SIngo Weinhold throw Exception(EIO, "Invalid ELF section header: " 513*402d77f6SIngo Weinhold "invalid name index: %lu.", nameIndex); 514*402d77f6SIngo Weinhold } 515*402d77f6SIngo Weinhold info.name = fSectionHeaderStrings + nameIndex; 516*402d77f6SIngo Weinhold } else { 517*402d77f6SIngo Weinhold info.name = ""; 518*402d77f6SIngo Weinhold } 519*402d77f6SIngo Weinhold 520*402d77f6SIngo Weinhold info.type = type; 521*402d77f6SIngo Weinhold info.offset = offset; 522*402d77f6SIngo Weinhold info.size = size; 523*402d77f6SIngo Weinhold 524*402d77f6SIngo Weinhold 525*402d77f6SIngo Weinhold return true; 526*402d77f6SIngo Weinhold } 527*402d77f6SIngo Weinhold 528*402d77f6SIngo Weinhold // _SwapUInt16 529*402d77f6SIngo Weinhold static inline uint16_t _SwapUInt16(uint16_t value) 530*402d77f6SIngo Weinhold { 531*402d77f6SIngo Weinhold return ((value & 0xff) << 8) | (value >> 8); 532*402d77f6SIngo Weinhold } 533*402d77f6SIngo Weinhold 534*402d77f6SIngo Weinhold // _SwapUInt32 535*402d77f6SIngo Weinhold static inline uint32_t _SwapUInt32(uint32_t value) 536*402d77f6SIngo Weinhold { 537*402d77f6SIngo Weinhold return ((uint32_t)_SwapUInt16(value & 0xffff) << 16) 538*402d77f6SIngo Weinhold | _SwapUInt16(uint16_t(value >> 16)); 539*402d77f6SIngo Weinhold } 540*402d77f6SIngo Weinhold 541*402d77f6SIngo Weinhold private: 542*402d77f6SIngo Weinhold int fFD; 543*402d77f6SIngo Weinhold bool fHostEndianess; 544*402d77f6SIngo Weinhold off_t fFileSize; 545*402d77f6SIngo Weinhold uint32_t fELFHeaderSize; 546*402d77f6SIngo Weinhold uint32_t fSectionHeaderTableOffset; 547*402d77f6SIngo Weinhold uint32_t fSectionHeaderSize; 548*402d77f6SIngo Weinhold uint32_t fSectionHeaderCount; 549*402d77f6SIngo Weinhold char* fSectionHeaderStrings; 550*402d77f6SIngo Weinhold int fSectionHeaderStringsLength; 551*402d77f6SIngo Weinhold }; 552*402d77f6SIngo Weinhold 553*402d77f6SIngo Weinhold 554*402d77f6SIngo Weinhold // main 555*402d77f6SIngo Weinhold int 556*402d77f6SIngo Weinhold main(int argc, const char* const* argv) 557*402d77f6SIngo Weinhold { 558*402d77f6SIngo Weinhold sArgc = argc; 559*402d77f6SIngo Weinhold sArgv = argv; 560*402d77f6SIngo Weinhold 561*402d77f6SIngo Weinhold if (argc < 3) 562*402d77f6SIngo Weinhold print_usage_and_exit(true); 563*402d77f6SIngo Weinhold 564*402d77f6SIngo Weinhold // parameters 565*402d77f6SIngo Weinhold const char* fileName = argv[1]; 566*402d77f6SIngo Weinhold const char* revisionString = argv[2]; 567*402d77f6SIngo Weinhold uint32_t revision = atol(revisionString); 568*402d77f6SIngo Weinhold 569*402d77f6SIngo Weinhold try { 570*402d77f6SIngo Weinhold ELFObject elfObject; 571*402d77f6SIngo Weinhold elfObject.SetTo(fileName); 572*402d77f6SIngo Weinhold 573*402d77f6SIngo Weinhold // find haiku revision section 574*402d77f6SIngo Weinhold SectionInfo info; 575*402d77f6SIngo Weinhold if (!elfObject.FindSectionByName("_haiku_revision", info)) { 576*402d77f6SIngo Weinhold fprintf(stderr, "haiku revision section not found\n"); 577*402d77f6SIngo Weinhold exit(1); 578*402d77f6SIngo Weinhold } 579*402d77f6SIngo Weinhold 580*402d77f6SIngo Weinhold // convert revision number to object endianess and write to section 581*402d77f6SIngo Weinhold uint32_t revisionBuffer = elfObject.GetUInt32(revision); 582*402d77f6SIngo Weinhold elfObject.Write(info.offset, &revisionBuffer, sizeof(revisionBuffer), 583*402d77f6SIngo Weinhold "Failed to write revision."); 584*402d77f6SIngo Weinhold 585*402d77f6SIngo Weinhold } catch (Exception exception) { 586*402d77f6SIngo Weinhold if (exception.Description() == "") { 587*402d77f6SIngo Weinhold fprintf(stderr, "%s\n", strerror(exception.Error())); 588*402d77f6SIngo Weinhold } else { 589*402d77f6SIngo Weinhold fprintf(stderr, "%s: %s\n", exception.Description().c_str(), 590*402d77f6SIngo Weinhold strerror(exception.Error())); 591*402d77f6SIngo Weinhold } 592*402d77f6SIngo Weinhold exit(1); 593*402d77f6SIngo Weinhold } 594*402d77f6SIngo Weinhold 595*402d77f6SIngo Weinhold return 0; 596*402d77f6SIngo Weinhold } 597