1f325ba9dSStephen Wilson //===-- ELFHeader.cpp ----------------------------------------- -*- C++ -*-===// 2f325ba9dSStephen Wilson // 3f325ba9dSStephen Wilson // The LLVM Compiler Infrastructure 4f325ba9dSStephen Wilson // 5f325ba9dSStephen Wilson // This file is distributed under the University of Illinois Open Source 6f325ba9dSStephen Wilson // License. See LICENSE.TXT for details. 7f325ba9dSStephen Wilson // 8f325ba9dSStephen Wilson //===----------------------------------------------------------------------===// 9f325ba9dSStephen Wilson 10f325ba9dSStephen Wilson #include <cstring> 11f325ba9dSStephen Wilson 12f325ba9dSStephen Wilson #include "lldb/Core/DataExtractor.h" 13f325ba9dSStephen Wilson 14f325ba9dSStephen Wilson #include "ELFHeader.h" 15f325ba9dSStephen Wilson 16f325ba9dSStephen Wilson using namespace elf; 17f325ba9dSStephen Wilson using namespace lldb; 18f325ba9dSStephen Wilson using namespace llvm::ELF; 19f325ba9dSStephen Wilson 20f325ba9dSStephen Wilson //------------------------------------------------------------------------------ 21f325ba9dSStephen Wilson // Static utility functions. 22f325ba9dSStephen Wilson // 23f325ba9dSStephen Wilson // GetMaxU64 and GetMaxS64 wrap the similarly named methods from DataExtractor 24f325ba9dSStephen Wilson // with error handling code and provide for parsing a sequence of values. 25f325ba9dSStephen Wilson static bool 26f325ba9dSStephen Wilson GetMaxU64(const lldb_private::DataExtractor &data, 27*c7bece56SGreg Clayton lldb::offset_t *offset, 28*c7bece56SGreg Clayton uint64_t *value, 29*c7bece56SGreg Clayton uint32_t byte_size) 30f325ba9dSStephen Wilson { 31*c7bece56SGreg Clayton const lldb::offset_t saved_offset = *offset; 32f325ba9dSStephen Wilson *value = data.GetMaxU64(offset, byte_size); 33f325ba9dSStephen Wilson return *offset != saved_offset; 34f325ba9dSStephen Wilson } 35f325ba9dSStephen Wilson 36f325ba9dSStephen Wilson static bool 37f325ba9dSStephen Wilson GetMaxU64(const lldb_private::DataExtractor &data, 38*c7bece56SGreg Clayton lldb::offset_t *offset, 39*c7bece56SGreg Clayton uint64_t *value, 40*c7bece56SGreg Clayton uint32_t byte_size, 41f325ba9dSStephen Wilson uint32_t count) 42f325ba9dSStephen Wilson { 43*c7bece56SGreg Clayton lldb::offset_t saved_offset = *offset; 44f325ba9dSStephen Wilson 45f325ba9dSStephen Wilson for (uint32_t i = 0; i < count; ++i, ++value) 46f325ba9dSStephen Wilson { 47f325ba9dSStephen Wilson if (GetMaxU64(data, offset, value, byte_size) == false) 48f325ba9dSStephen Wilson { 49f325ba9dSStephen Wilson *offset = saved_offset; 50f325ba9dSStephen Wilson return false; 51f325ba9dSStephen Wilson } 52f325ba9dSStephen Wilson } 53f325ba9dSStephen Wilson return true; 54f325ba9dSStephen Wilson } 55f325ba9dSStephen Wilson 56f325ba9dSStephen Wilson static bool 57f325ba9dSStephen Wilson GetMaxS64(const lldb_private::DataExtractor &data, 58*c7bece56SGreg Clayton lldb::offset_t *offset, 59*c7bece56SGreg Clayton int64_t *value, 60*c7bece56SGreg Clayton uint32_t byte_size) 61f325ba9dSStephen Wilson { 62*c7bece56SGreg Clayton const lldb::offset_t saved_offset = *offset; 63f325ba9dSStephen Wilson *value = data.GetMaxS64(offset, byte_size); 64f325ba9dSStephen Wilson return *offset != saved_offset; 65f325ba9dSStephen Wilson } 66f325ba9dSStephen Wilson 67f325ba9dSStephen Wilson static bool 68f325ba9dSStephen Wilson GetMaxS64(const lldb_private::DataExtractor &data, 69*c7bece56SGreg Clayton lldb::offset_t *offset, 70*c7bece56SGreg Clayton int64_t *value, 71*c7bece56SGreg Clayton uint32_t byte_size, 72f325ba9dSStephen Wilson uint32_t count) 73f325ba9dSStephen Wilson { 74*c7bece56SGreg Clayton lldb::offset_t saved_offset = *offset; 75f325ba9dSStephen Wilson 76f325ba9dSStephen Wilson for (uint32_t i = 0; i < count; ++i, ++value) 77f325ba9dSStephen Wilson { 78f325ba9dSStephen Wilson if (GetMaxS64(data, offset, value, byte_size) == false) 79f325ba9dSStephen Wilson { 80f325ba9dSStephen Wilson *offset = saved_offset; 81f325ba9dSStephen Wilson return false; 82f325ba9dSStephen Wilson } 83f325ba9dSStephen Wilson } 84f325ba9dSStephen Wilson return true; 85f325ba9dSStephen Wilson } 86f325ba9dSStephen Wilson 87f325ba9dSStephen Wilson //------------------------------------------------------------------------------ 88f325ba9dSStephen Wilson // ELFHeader 89f325ba9dSStephen Wilson 90f325ba9dSStephen Wilson ELFHeader::ELFHeader() 91f325ba9dSStephen Wilson { 92f325ba9dSStephen Wilson memset(this, 0, sizeof(ELFHeader)); 93f325ba9dSStephen Wilson } 94f325ba9dSStephen Wilson 95f325ba9dSStephen Wilson ByteOrder 96f325ba9dSStephen Wilson ELFHeader::GetByteOrder() const 97f325ba9dSStephen Wilson { 98f325ba9dSStephen Wilson if (e_ident[EI_DATA] == ELFDATA2MSB) 99f325ba9dSStephen Wilson return eByteOrderBig; 100f325ba9dSStephen Wilson if (e_ident[EI_DATA] == ELFDATA2LSB) 101f325ba9dSStephen Wilson return eByteOrderLittle; 102f325ba9dSStephen Wilson return eByteOrderInvalid; 103f325ba9dSStephen Wilson } 104f325ba9dSStephen Wilson 105f325ba9dSStephen Wilson bool 106*c7bece56SGreg Clayton ELFHeader::Parse(lldb_private::DataExtractor &data, lldb::offset_t *offset) 107f325ba9dSStephen Wilson { 108f325ba9dSStephen Wilson // Read e_ident. This provides byte order and address size info. 109f325ba9dSStephen Wilson if (data.GetU8(offset, &e_ident, EI_NIDENT) == NULL) 110f325ba9dSStephen Wilson return false; 111f325ba9dSStephen Wilson 112f325ba9dSStephen Wilson const unsigned byte_size = Is32Bit() ? 4 : 8; 113f325ba9dSStephen Wilson data.SetByteOrder(GetByteOrder()); 114f325ba9dSStephen Wilson data.SetAddressByteSize(byte_size); 115f325ba9dSStephen Wilson 116f325ba9dSStephen Wilson // Read e_type and e_machine. 117f325ba9dSStephen Wilson if (data.GetU16(offset, &e_type, 2) == NULL) 118f325ba9dSStephen Wilson return false; 119f325ba9dSStephen Wilson 120f325ba9dSStephen Wilson // Read e_version. 121f325ba9dSStephen Wilson if (data.GetU32(offset, &e_version, 1) == NULL) 122f325ba9dSStephen Wilson return false; 123f325ba9dSStephen Wilson 124f325ba9dSStephen Wilson // Read e_entry, e_phoff and e_shoff. 125f325ba9dSStephen Wilson if (GetMaxU64(data, offset, &e_entry, byte_size, 3) == false) 126f325ba9dSStephen Wilson return false; 127f325ba9dSStephen Wilson 128f325ba9dSStephen Wilson // Read e_flags. 129f325ba9dSStephen Wilson if (data.GetU32(offset, &e_flags, 1) == NULL) 130f325ba9dSStephen Wilson return false; 131f325ba9dSStephen Wilson 132f325ba9dSStephen Wilson // Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum and 133f325ba9dSStephen Wilson // e_shstrndx. 134f325ba9dSStephen Wilson if (data.GetU16(offset, &e_ehsize, 6) == NULL) 135f325ba9dSStephen Wilson return false; 136f325ba9dSStephen Wilson 137f325ba9dSStephen Wilson return true; 138f325ba9dSStephen Wilson } 139f325ba9dSStephen Wilson 140f325ba9dSStephen Wilson bool 141f325ba9dSStephen Wilson ELFHeader::MagicBytesMatch(const uint8_t *magic) 142f325ba9dSStephen Wilson { 143f325ba9dSStephen Wilson return memcmp(magic, ElfMagic, strlen(ElfMagic)) == 0; 144f325ba9dSStephen Wilson } 145f325ba9dSStephen Wilson 146f325ba9dSStephen Wilson unsigned 147f325ba9dSStephen Wilson ELFHeader::AddressSizeInBytes(const uint8_t *magic) 148f325ba9dSStephen Wilson { 149f325ba9dSStephen Wilson unsigned address_size = 0; 150f325ba9dSStephen Wilson 151f325ba9dSStephen Wilson switch (magic[EI_CLASS]) 152f325ba9dSStephen Wilson { 153f325ba9dSStephen Wilson case ELFCLASS32: 154f325ba9dSStephen Wilson address_size = 4; 155f325ba9dSStephen Wilson break; 156f325ba9dSStephen Wilson 157f325ba9dSStephen Wilson case ELFCLASS64: 158f325ba9dSStephen Wilson address_size = 8; 159f325ba9dSStephen Wilson break; 160f325ba9dSStephen Wilson } 161f325ba9dSStephen Wilson return address_size; 162f325ba9dSStephen Wilson } 163f325ba9dSStephen Wilson 16443fe645bSStephen Wilson unsigned 16543fe645bSStephen Wilson ELFHeader::GetRelocationJumpSlotType() const 16643fe645bSStephen Wilson { 16743fe645bSStephen Wilson unsigned slot = 0; 16843fe645bSStephen Wilson 16943fe645bSStephen Wilson switch (e_machine) 17043fe645bSStephen Wilson { 17143fe645bSStephen Wilson default: 17243fe645bSStephen Wilson assert(false && "architecture not supported"); 17343fe645bSStephen Wilson break; 17443fe645bSStephen Wilson case EM_386: 17543fe645bSStephen Wilson case EM_486: 17643fe645bSStephen Wilson slot = R_386_JUMP_SLOT; 17743fe645bSStephen Wilson break; 17843fe645bSStephen Wilson case EM_X86_64: 17943fe645bSStephen Wilson slot = R_X86_64_JUMP_SLOT; 18043fe645bSStephen Wilson break; 18143fe645bSStephen Wilson case EM_ARM: 18243fe645bSStephen Wilson slot = R_ARM_JUMP_SLOT; 18343fe645bSStephen Wilson break; 18443fe645bSStephen Wilson case EM_MBLAZE: 18543fe645bSStephen Wilson slot = R_MICROBLAZE_JUMP_SLOT; 18643fe645bSStephen Wilson } 18743fe645bSStephen Wilson 18843fe645bSStephen Wilson return slot; 18943fe645bSStephen Wilson } 19043fe645bSStephen Wilson 191f325ba9dSStephen Wilson //------------------------------------------------------------------------------ 192f325ba9dSStephen Wilson // ELFSectionHeader 193f325ba9dSStephen Wilson 194f325ba9dSStephen Wilson ELFSectionHeader::ELFSectionHeader() 195f325ba9dSStephen Wilson { 196f325ba9dSStephen Wilson memset(this, 0, sizeof(ELFSectionHeader)); 197f325ba9dSStephen Wilson } 198f325ba9dSStephen Wilson 199f325ba9dSStephen Wilson bool 200f325ba9dSStephen Wilson ELFSectionHeader::Parse(const lldb_private::DataExtractor &data, 201*c7bece56SGreg Clayton lldb::offset_t *offset) 202f325ba9dSStephen Wilson { 203f325ba9dSStephen Wilson const unsigned byte_size = data.GetAddressByteSize(); 204f325ba9dSStephen Wilson 205f325ba9dSStephen Wilson // Read sh_name and sh_type. 206f325ba9dSStephen Wilson if (data.GetU32(offset, &sh_name, 2) == NULL) 207f325ba9dSStephen Wilson return false; 208f325ba9dSStephen Wilson 209f325ba9dSStephen Wilson // Read sh_flags. 210f325ba9dSStephen Wilson if (GetMaxU64(data, offset, &sh_flags, byte_size) == false) 211f325ba9dSStephen Wilson return false; 212f325ba9dSStephen Wilson 213f325ba9dSStephen Wilson // Read sh_addr, sh_off and sh_size. 214f325ba9dSStephen Wilson if (GetMaxU64(data, offset, &sh_addr, byte_size, 3) == false) 215f325ba9dSStephen Wilson return false; 216f325ba9dSStephen Wilson 217f325ba9dSStephen Wilson // Read sh_link and sh_info. 218f325ba9dSStephen Wilson if (data.GetU32(offset, &sh_link, 2) == NULL) 219f325ba9dSStephen Wilson return false; 220f325ba9dSStephen Wilson 221f325ba9dSStephen Wilson // Read sh_addralign and sh_entsize. 222f325ba9dSStephen Wilson if (GetMaxU64(data, offset, &sh_addralign, byte_size, 2) == false) 223f325ba9dSStephen Wilson return false; 224f325ba9dSStephen Wilson 225f325ba9dSStephen Wilson return true; 226f325ba9dSStephen Wilson } 227f325ba9dSStephen Wilson 228f325ba9dSStephen Wilson //------------------------------------------------------------------------------ 229f325ba9dSStephen Wilson // ELFSymbol 230f325ba9dSStephen Wilson 231f325ba9dSStephen Wilson ELFSymbol::ELFSymbol() 232f325ba9dSStephen Wilson { 233f325ba9dSStephen Wilson memset(this, 0, sizeof(ELFSymbol)); 234f325ba9dSStephen Wilson } 235f325ba9dSStephen Wilson 236f325ba9dSStephen Wilson bool 237*c7bece56SGreg Clayton ELFSymbol::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset) 238f325ba9dSStephen Wilson { 239f325ba9dSStephen Wilson const unsigned byte_size = data.GetAddressByteSize(); 240f325ba9dSStephen Wilson const bool parsing_32 = byte_size == 4; 241f325ba9dSStephen Wilson 242f325ba9dSStephen Wilson // Read st_name. 243f325ba9dSStephen Wilson if (data.GetU32(offset, &st_name, 1) == NULL) 244f325ba9dSStephen Wilson return false; 245f325ba9dSStephen Wilson 246f325ba9dSStephen Wilson if (parsing_32) 247f325ba9dSStephen Wilson { 248f325ba9dSStephen Wilson // Read st_value and st_size. 249f325ba9dSStephen Wilson if (GetMaxU64(data, offset, &st_value, byte_size, 2) == false) 250f325ba9dSStephen Wilson return false; 251f325ba9dSStephen Wilson 252f325ba9dSStephen Wilson // Read st_info and st_other. 253f325ba9dSStephen Wilson if (data.GetU8(offset, &st_info, 2) == NULL) 254f325ba9dSStephen Wilson return false; 255f325ba9dSStephen Wilson 256f325ba9dSStephen Wilson // Read st_shndx. 257f325ba9dSStephen Wilson if (data.GetU16(offset, &st_shndx, 1) == NULL) 258f325ba9dSStephen Wilson return false; 259f325ba9dSStephen Wilson } 260f325ba9dSStephen Wilson else 261f325ba9dSStephen Wilson { 262f325ba9dSStephen Wilson // Read st_info and st_other. 263f325ba9dSStephen Wilson if (data.GetU8(offset, &st_info, 2) == NULL) 264f325ba9dSStephen Wilson return false; 265f325ba9dSStephen Wilson 266f325ba9dSStephen Wilson // Read st_shndx. 267f325ba9dSStephen Wilson if (data.GetU16(offset, &st_shndx, 1) == NULL) 268f325ba9dSStephen Wilson return false; 269f325ba9dSStephen Wilson 270f325ba9dSStephen Wilson // Read st_value and st_size. 271f325ba9dSStephen Wilson if (data.GetU64(offset, &st_value, 2) == NULL) 272f325ba9dSStephen Wilson return false; 273f325ba9dSStephen Wilson } 274f325ba9dSStephen Wilson return true; 275f325ba9dSStephen Wilson } 276f325ba9dSStephen Wilson 277f325ba9dSStephen Wilson //------------------------------------------------------------------------------ 278f325ba9dSStephen Wilson // ELFProgramHeader 279f325ba9dSStephen Wilson 280f325ba9dSStephen Wilson ELFProgramHeader::ELFProgramHeader() 281f325ba9dSStephen Wilson { 282f325ba9dSStephen Wilson memset(this, 0, sizeof(ELFProgramHeader)); 283f325ba9dSStephen Wilson } 284f325ba9dSStephen Wilson 285f325ba9dSStephen Wilson bool 286f325ba9dSStephen Wilson ELFProgramHeader::Parse(const lldb_private::DataExtractor &data, 287*c7bece56SGreg Clayton lldb::offset_t *offset) 288f325ba9dSStephen Wilson { 289f325ba9dSStephen Wilson const uint32_t byte_size = data.GetAddressByteSize(); 290f325ba9dSStephen Wilson const bool parsing_32 = byte_size == 4; 291f325ba9dSStephen Wilson 292f325ba9dSStephen Wilson // Read p_type; 293f325ba9dSStephen Wilson if (data.GetU32(offset, &p_type, 1) == NULL) 294f325ba9dSStephen Wilson return false; 295f325ba9dSStephen Wilson 296f325ba9dSStephen Wilson if (parsing_32) { 297f325ba9dSStephen Wilson // Read p_offset, p_vaddr, p_paddr, p_filesz and p_memsz. 298f325ba9dSStephen Wilson if (GetMaxU64(data, offset, &p_offset, byte_size, 5) == false) 299f325ba9dSStephen Wilson return false; 300f325ba9dSStephen Wilson 301f325ba9dSStephen Wilson // Read p_flags. 302f325ba9dSStephen Wilson if (data.GetU32(offset, &p_flags, 1) == NULL) 303f325ba9dSStephen Wilson return false; 304f325ba9dSStephen Wilson 305f325ba9dSStephen Wilson // Read p_align. 306f325ba9dSStephen Wilson if (GetMaxU64(data, offset, &p_align, byte_size) == false) 307f325ba9dSStephen Wilson return false; 308f325ba9dSStephen Wilson } 309f325ba9dSStephen Wilson else { 310f325ba9dSStephen Wilson // Read p_flags. 311f325ba9dSStephen Wilson if (data.GetU32(offset, &p_flags, 1) == NULL) 312f325ba9dSStephen Wilson return false; 313f325ba9dSStephen Wilson 314f325ba9dSStephen Wilson // Read p_offset, p_vaddr, p_paddr, p_filesz, p_memsz and p_align. 315f325ba9dSStephen Wilson if (GetMaxU64(data, offset, &p_offset, byte_size, 6) == false) 316f325ba9dSStephen Wilson return false; 317f325ba9dSStephen Wilson } 318f325ba9dSStephen Wilson 319f325ba9dSStephen Wilson return true; 320f325ba9dSStephen Wilson } 321f325ba9dSStephen Wilson 322f325ba9dSStephen Wilson //------------------------------------------------------------------------------ 323f325ba9dSStephen Wilson // ELFDynamic 324f325ba9dSStephen Wilson 325f325ba9dSStephen Wilson ELFDynamic::ELFDynamic() 326f325ba9dSStephen Wilson { 327f325ba9dSStephen Wilson memset(this, 0, sizeof(ELFDynamic)); 328f325ba9dSStephen Wilson } 329f325ba9dSStephen Wilson 330f325ba9dSStephen Wilson bool 331*c7bece56SGreg Clayton ELFDynamic::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset) 332f325ba9dSStephen Wilson { 333f325ba9dSStephen Wilson const unsigned byte_size = data.GetAddressByteSize(); 334f325ba9dSStephen Wilson return GetMaxS64(data, offset, &d_tag, byte_size, 2); 335f325ba9dSStephen Wilson } 336f325ba9dSStephen Wilson 33743fe645bSStephen Wilson //------------------------------------------------------------------------------ 33843fe645bSStephen Wilson // ELFRel 33943fe645bSStephen Wilson 34043fe645bSStephen Wilson ELFRel::ELFRel() 34143fe645bSStephen Wilson { 34243fe645bSStephen Wilson memset(this, 0, sizeof(ELFRel)); 34343fe645bSStephen Wilson } 34443fe645bSStephen Wilson 34543fe645bSStephen Wilson bool 346*c7bece56SGreg Clayton ELFRel::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset) 34743fe645bSStephen Wilson { 34843fe645bSStephen Wilson const unsigned byte_size = data.GetAddressByteSize(); 34943fe645bSStephen Wilson 35043fe645bSStephen Wilson // Read r_offset and r_info. 35143fe645bSStephen Wilson if (GetMaxU64(data, offset, &r_offset, byte_size, 2) == false) 35243fe645bSStephen Wilson return false; 35343fe645bSStephen Wilson 35443fe645bSStephen Wilson return true; 35543fe645bSStephen Wilson } 35643fe645bSStephen Wilson 35743fe645bSStephen Wilson //------------------------------------------------------------------------------ 35843fe645bSStephen Wilson // ELFRela 35943fe645bSStephen Wilson 36043fe645bSStephen Wilson ELFRela::ELFRela() 36143fe645bSStephen Wilson { 36243fe645bSStephen Wilson memset(this, 0, sizeof(ELFRela)); 36343fe645bSStephen Wilson } 36443fe645bSStephen Wilson 36543fe645bSStephen Wilson bool 366*c7bece56SGreg Clayton ELFRela::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset) 36743fe645bSStephen Wilson { 36843fe645bSStephen Wilson const unsigned byte_size = data.GetAddressByteSize(); 36943fe645bSStephen Wilson 37043fe645bSStephen Wilson // Read r_offset and r_info. 37143fe645bSStephen Wilson if (GetMaxU64(data, offset, &r_offset, byte_size, 2) == false) 37243fe645bSStephen Wilson return false; 37343fe645bSStephen Wilson 37443fe645bSStephen Wilson // Read r_addend; 37543fe645bSStephen Wilson if (GetMaxS64(data, offset, &r_addend, byte_size) == false) 37643fe645bSStephen Wilson return false; 37743fe645bSStephen Wilson 37843fe645bSStephen Wilson return true; 37943fe645bSStephen Wilson } 38043fe645bSStephen Wilson 381f325ba9dSStephen Wilson 382