2010-07-13 23:07:23 +00:00
//===-- ObjectFileELF.cpp ------------------------------------- -*- C++ -*-===//
2010-06-08 16:52:24 +00:00
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
# include "ObjectFileELF.h"
2010-07-13 23:07:23 +00:00
# include <cassert>
2010-06-08 16:52:24 +00:00
# include <algorithm>
2011-01-15 00:08:44 +00:00
# include "lldb/Core/ArchSpec.h"
2010-06-08 16:52:24 +00:00
# include "lldb/Core/DataBuffer.h"
# include "lldb/Core/Error.h"
2010-07-13 23:07:23 +00:00
# include "lldb/Core/FileSpecList.h"
2013-12-02 17:49:13 +00:00
# include "lldb/Core/Log.h"
2011-03-07 23:44:08 +00:00
# include "lldb/Core/Module.h"
2013-04-24 22:29:28 +00:00
# include "lldb/Core/ModuleSpec.h"
2010-06-08 16:52:24 +00:00
# include "lldb/Core/PluginManager.h"
# include "lldb/Core/Section.h"
# include "lldb/Core/Stream.h"
2014-03-25 19:29:09 +00:00
# include "lldb/Core/Timer.h"
2013-09-24 15:34:13 +00:00
# include "lldb/Symbol/DWARFCallFrameInfo.h"
2011-03-07 23:44:08 +00:00
# include "lldb/Symbol/SymbolContext.h"
2014-02-06 19:02:19 +00:00
# include "lldb/Target/SectionLoadList.h"
2013-10-11 17:39:07 +00:00
# include "lldb/Target/Target.h"
2014-08-19 17:18:29 +00:00
# include "lldb/Host/HostInfo.h"
2010-06-08 16:52:24 +00:00
2011-03-30 16:07:05 +00:00
# include "llvm/ADT/PointerUnion.h"
2014-08-19 17:18:29 +00:00
# include "llvm/ADT/StringRef.h"
2014-06-25 05:42:32 +00:00
# include "llvm/Support/MathExtras.h"
2011-03-30 16:07:05 +00:00
2010-07-13 23:07:23 +00:00
# define CASE_AND_STREAM(s, def, width) \
case def : s - > Printf ( " %-*s " , width , # def ) ; break ;
2010-06-08 16:52:24 +00:00
using namespace lldb ;
using namespace lldb_private ;
2010-07-13 23:07:23 +00:00
using namespace elf ;
using namespace llvm : : ELF ;
2010-06-08 16:52:24 +00:00
2011-03-30 16:07:05 +00:00
namespace {
2014-06-27 16:52:49 +00:00
// ELF note owner definitions
const char * const LLDB_NT_OWNER_FREEBSD = " FreeBSD " ;
const char * const LLDB_NT_OWNER_GNU = " GNU " ;
const char * const LLDB_NT_OWNER_NETBSD = " NetBSD " ;
2014-07-16 15:03:10 +00:00
const char * const LLDB_NT_OWNER_CSR = " csr " ;
2015-03-18 10:36:27 +00:00
const char * const LLDB_NT_OWNER_ANDROID = " Android " ;
2014-06-27 16:52:49 +00:00
// ELF note type definitions
const elf_word LLDB_NT_FREEBSD_ABI_TAG = 0x01 ;
const elf_word LLDB_NT_FREEBSD_ABI_SIZE = 4 ;
const elf_word LLDB_NT_GNU_ABI_TAG = 0x01 ;
const elf_word LLDB_NT_GNU_ABI_SIZE = 16 ;
const elf_word LLDB_NT_GNU_BUILD_ID_TAG = 0x03 ;
const elf_word LLDB_NT_NETBSD_ABI_TAG = 0x01 ;
const elf_word LLDB_NT_NETBSD_ABI_SIZE = 4 ;
// GNU ABI note OS constants
const elf_word LLDB_NT_GNU_ABI_OS_LINUX = 0x00 ;
const elf_word LLDB_NT_GNU_ABI_OS_HURD = 0x01 ;
const elf_word LLDB_NT_GNU_ABI_OS_SOLARIS = 0x02 ;
2011-03-30 16:07:05 +00:00
//===----------------------------------------------------------------------===//
/// @class ELFRelocation
/// @brief Generic wrapper for ELFRel and ELFRela.
///
/// This helper class allows us to parse both ELFRel and ELFRela relocation
/// entries in a generic manner.
class ELFRelocation
{
public :
/// Constructs an ELFRelocation entry with a personality as given by @p
/// type.
///
/// @param type Either DT_REL or DT_RELA. Any other value is invalid.
ELFRelocation ( unsigned type ) ;
~ ELFRelocation ( ) ;
bool
2013-01-25 18:06:21 +00:00
Parse ( const lldb_private : : DataExtractor & data , lldb : : offset_t * offset ) ;
2011-03-30 16:07:05 +00:00
static unsigned
RelocType32 ( const ELFRelocation & rel ) ;
static unsigned
RelocType64 ( const ELFRelocation & rel ) ;
static unsigned
RelocSymbol32 ( const ELFRelocation & rel ) ;
static unsigned
RelocSymbol64 ( const ELFRelocation & rel ) ;
2014-03-05 10:12:43 +00:00
static unsigned
RelocOffset32 ( const ELFRelocation & rel ) ;
static unsigned
RelocOffset64 ( const ELFRelocation & rel ) ;
static unsigned
RelocAddend32 ( const ELFRelocation & rel ) ;
static unsigned
RelocAddend64 ( const ELFRelocation & rel ) ;
2011-03-30 16:07:05 +00:00
private :
typedef llvm : : PointerUnion < ELFRel * , ELFRela * > RelocUnion ;
RelocUnion reloc ;
} ;
ELFRelocation : : ELFRelocation ( unsigned type )
{
2014-03-05 10:12:43 +00:00
if ( type = = DT_REL | | type = = SHT_REL )
2011-03-30 16:07:05 +00:00
reloc = new ELFRel ( ) ;
2014-03-05 10:12:43 +00:00
else if ( type = = DT_RELA | | type = = SHT_RELA )
2011-03-30 16:07:05 +00:00
reloc = new ELFRela ( ) ;
else {
assert ( false & & " unexpected relocation type " ) ;
reloc = static_cast < ELFRel * > ( NULL ) ;
}
}
ELFRelocation : : ~ ELFRelocation ( )
{
if ( reloc . is < ELFRel * > ( ) )
delete reloc . get < ELFRel * > ( ) ;
else
delete reloc . get < ELFRela * > ( ) ;
}
bool
2013-01-25 18:06:21 +00:00
ELFRelocation : : Parse ( const lldb_private : : DataExtractor & data , lldb : : offset_t * offset )
2011-03-30 16:07:05 +00:00
{
if ( reloc . is < ELFRel * > ( ) )
return reloc . get < ELFRel * > ( ) - > Parse ( data , offset ) ;
else
return reloc . get < ELFRela * > ( ) - > Parse ( data , offset ) ;
}
unsigned
ELFRelocation : : RelocType32 ( const ELFRelocation & rel )
{
if ( rel . reloc . is < ELFRel * > ( ) )
return ELFRel : : RelocType32 ( * rel . reloc . get < ELFRel * > ( ) ) ;
else
return ELFRela : : RelocType32 ( * rel . reloc . get < ELFRela * > ( ) ) ;
}
unsigned
ELFRelocation : : RelocType64 ( const ELFRelocation & rel )
{
if ( rel . reloc . is < ELFRel * > ( ) )
return ELFRel : : RelocType64 ( * rel . reloc . get < ELFRel * > ( ) ) ;
else
return ELFRela : : RelocType64 ( * rel . reloc . get < ELFRela * > ( ) ) ;
}
unsigned
ELFRelocation : : RelocSymbol32 ( const ELFRelocation & rel )
{
if ( rel . reloc . is < ELFRel * > ( ) )
return ELFRel : : RelocSymbol32 ( * rel . reloc . get < ELFRel * > ( ) ) ;
else
return ELFRela : : RelocSymbol32 ( * rel . reloc . get < ELFRela * > ( ) ) ;
}
unsigned
ELFRelocation : : RelocSymbol64 ( const ELFRelocation & rel )
{
if ( rel . reloc . is < ELFRel * > ( ) )
return ELFRel : : RelocSymbol64 ( * rel . reloc . get < ELFRel * > ( ) ) ;
else
return ELFRela : : RelocSymbol64 ( * rel . reloc . get < ELFRela * > ( ) ) ;
}
2014-03-05 10:12:43 +00:00
unsigned
ELFRelocation : : RelocOffset32 ( const ELFRelocation & rel )
{
if ( rel . reloc . is < ELFRel * > ( ) )
return rel . reloc . get < ELFRel * > ( ) - > r_offset ;
else
return rel . reloc . get < ELFRela * > ( ) - > r_offset ;
}
unsigned
ELFRelocation : : RelocOffset64 ( const ELFRelocation & rel )
{
if ( rel . reloc . is < ELFRel * > ( ) )
return rel . reloc . get < ELFRel * > ( ) - > r_offset ;
else
return rel . reloc . get < ELFRela * > ( ) - > r_offset ;
}
unsigned
ELFRelocation : : RelocAddend32 ( const ELFRelocation & rel )
{
if ( rel . reloc . is < ELFRel * > ( ) )
return 0 ;
else
return rel . reloc . get < ELFRela * > ( ) - > r_addend ;
}
unsigned
ELFRelocation : : RelocAddend64 ( const ELFRelocation & rel )
{
if ( rel . reloc . is < ELFRel * > ( ) )
return 0 ;
else
return rel . reloc . get < ELFRela * > ( ) - > r_addend ;
}
2011-03-30 16:07:05 +00:00
} // end anonymous namespace
2013-12-02 17:49:13 +00:00
bool
ELFNote : : Parse ( const DataExtractor & data , lldb : : offset_t * offset )
{
// Read all fields.
if ( data . GetU32 ( offset , & n_namesz , 3 ) = = NULL )
return false ;
// The name field is required to be nul-terminated, and n_namesz
// includes the terminating nul in observed implementations (contrary
// to the ELF-64 spec). A special case is needed for cores generated
// by some older Linux versions, which write a note named "CORE"
// without a nul terminator and n_namesz = 4.
if ( n_namesz = = 4 )
{
char buf [ 4 ] ;
if ( data . ExtractBytes ( * offset , 4 , data . GetByteOrder ( ) , buf ) ! = 4 )
return false ;
if ( strncmp ( buf , " CORE " , 4 ) = = 0 )
{
n_name = " CORE " ;
* offset + = 4 ;
return true ;
}
}
const char * cstr = data . GetCStr ( offset , llvm : : RoundUpToAlignment ( n_namesz , 4 ) ) ;
if ( cstr = = NULL )
{
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_SYMBOLS ) ) ;
if ( log )
log - > Printf ( " Failed to parse note name lacking nul terminator " ) ;
return false ;
}
n_name = cstr ;
return true ;
}
2014-08-27 12:09:39 +00:00
static uint32_t
kalimbaVariantFromElfFlags ( const elf : : elf_word e_flags )
{
const uint32_t dsp_rev = e_flags & 0xFF ;
uint32_t kal_arch_variant = LLDB_INVALID_CPUTYPE ;
switch ( dsp_rev )
{
// TODO(mg11) Support more variants
case 10 :
2014-09-29 08:02:24 +00:00
kal_arch_variant = llvm : : Triple : : KalimbaSubArch_v3 ;
2014-08-27 12:09:39 +00:00
break ;
case 14 :
2014-09-29 08:02:24 +00:00
kal_arch_variant = llvm : : Triple : : KalimbaSubArch_v4 ;
break ;
case 17 :
case 20 :
kal_arch_variant = llvm : : Triple : : KalimbaSubArch_v5 ;
2014-08-27 12:09:39 +00:00
break ;
default :
break ;
}
return kal_arch_variant ;
}
2015-03-17 11:43:56 +00:00
static uint32_t
mipsVariantFromElfFlags ( const elf : : elf_word e_flags , uint32_t endian )
{
const uint32_t mips_arch = e_flags & llvm : : ELF : : EF_MIPS_ARCH ;
uint32_t arch_variant = LLDB_INVALID_CPUTYPE ;
switch ( mips_arch )
{
case llvm : : ELF : : EF_MIPS_ARCH_64 :
if ( endian = = ELFDATA2LSB )
arch_variant = llvm : : Triple : : mips64el ;
else
arch_variant = llvm : : Triple : : mips64 ;
break ;
default :
break ;
}
return arch_variant ;
}
2014-08-27 12:09:39 +00:00
static uint32_t
subTypeFromElfHeader ( const elf : : ELFHeader & header )
{
2015-03-17 11:43:56 +00:00
if ( header . e_machine = = llvm : : ELF : : EM_MIPS )
return mipsVariantFromElfFlags ( header . e_flags ,
header . e_ident [ EI_DATA ] ) ;
2014-08-27 12:09:39 +00:00
return
llvm : : ELF : : EM_CSR_KALIMBA = = header . e_machine ?
kalimbaVariantFromElfFlags ( header . e_flags ) :
LLDB_INVALID_CPUTYPE ;
}
2014-09-29 08:02:24 +00:00
//! The kalimba toolchain identifies a code section as being
//! one with the SHT_PROGBITS set in the section sh_type and the top
//! bit in the 32-bit address field set.
static lldb : : SectionType
kalimbaSectionType (
const elf : : ELFHeader & header ,
const elf : : ELFSectionHeader & sect_hdr )
{
2014-10-15 08:21:54 +00:00
if ( llvm : : ELF : : EM_CSR_KALIMBA ! = header . e_machine )
2014-09-29 08:02:24 +00:00
{
return eSectionTypeOther ;
}
2014-10-15 08:21:54 +00:00
if ( llvm : : ELF : : SHT_NOBITS = = sect_hdr . sh_type )
{
return eSectionTypeZeroFill ;
}
if ( llvm : : ELF : : SHT_PROGBITS = = sect_hdr . sh_type )
{
const lldb : : addr_t KAL_CODE_BIT = 1 < < 31 ;
return KAL_CODE_BIT & sect_hdr . sh_addr ?
eSectionTypeCode : eSectionTypeData ;
}
return eSectionTypeOther ;
2014-09-29 08:02:24 +00:00
}
2014-03-25 19:29:09 +00:00
// Arbitrary constant used as UUID prefix for core files.
const uint32_t
ObjectFileELF : : g_core_uuid_magic ( 0xE210C ) ;
2010-07-13 23:07:23 +00:00
//------------------------------------------------------------------
// Static methods.
//------------------------------------------------------------------
2010-06-08 16:52:24 +00:00
void
ObjectFileELF : : Initialize ( )
{
2010-07-13 23:07:23 +00:00
PluginManager : : RegisterPlugin ( GetPluginNameStatic ( ) ,
GetPluginDescriptionStatic ( ) ,
2012-02-05 02:38:54 +00:00
CreateInstance ,
2013-04-24 22:29:28 +00:00
CreateMemoryInstance ,
GetModuleSpecifications ) ;
2010-06-08 16:52:24 +00:00
}
void
ObjectFileELF : : Terminate ( )
{
2010-07-13 23:07:23 +00:00
PluginManager : : UnregisterPlugin ( CreateInstance ) ;
2010-06-08 16:52:24 +00:00
}
2013-05-10 21:47:16 +00:00
lldb_private : : ConstString
2010-06-08 16:52:24 +00:00
ObjectFileELF : : GetPluginNameStatic ( )
{
2013-05-10 21:47:16 +00:00
static ConstString g_name ( " elf " ) ;
return g_name ;
2010-06-08 16:52:24 +00:00
}
const char *
ObjectFileELF : : GetPluginDescriptionStatic ( )
{
2010-07-13 23:07:23 +00:00
return " ELF object file reader. " ;
2010-06-08 16:52:24 +00:00
}
ObjectFile *
2012-02-24 01:59:29 +00:00
ObjectFileELF : : CreateInstance ( const lldb : : ModuleSP & module_sp ,
DataBufferSP & data_sp ,
2013-02-06 17:22:03 +00:00
lldb : : offset_t data_offset ,
const lldb_private : : FileSpec * file ,
lldb : : offset_t file_offset ,
lldb : : offset_t length )
2010-06-08 16:52:24 +00:00
{
2013-02-06 17:22:03 +00:00
if ( ! data_sp )
2010-06-08 16:52:24 +00:00
{
2015-02-23 23:47:09 +00:00
data_sp = file - > MemoryMapFileContentsIfLocal ( file_offset , length ) ;
2013-02-06 17:22:03 +00:00
data_offset = 0 ;
}
if ( data_sp & & data_sp - > GetByteSize ( ) > ( llvm : : ELF : : EI_NIDENT + data_offset ) )
{
const uint8_t * magic = data_sp - > GetBytes ( ) + data_offset ;
2010-07-13 23:07:23 +00:00
if ( ELFHeader : : MagicBytesMatch ( magic ) )
{
2013-02-06 17:22:03 +00:00
// Update the data to contain the entire file if it doesn't already
2013-02-07 21:30:54 +00:00
if ( data_sp - > GetByteSize ( ) < length ) {
2015-02-23 23:47:09 +00:00
data_sp = file - > MemoryMapFileContentsIfLocal ( file_offset , length ) ;
2013-02-07 21:49:54 +00:00
data_offset = 0 ;
magic = data_sp - > GetBytes ( ) ;
2013-02-07 21:30:54 +00:00
}
2010-07-13 23:07:23 +00:00
unsigned address_size = ELFHeader : : AddressSizeInBytes ( magic ) ;
if ( address_size = = 4 | | address_size = = 8 )
{
2013-04-18 22:45:39 +00:00
std : : unique_ptr < ObjectFileELF > objfile_ap ( new ObjectFileELF ( module_sp , data_sp , data_offset , file , file_offset , length ) ) ;
2011-02-24 19:16:15 +00:00
ArchSpec spec ;
if ( objfile_ap - > GetArchitecture ( spec ) & &
objfile_ap - > SetModulesArchitecture ( spec ) )
2010-07-13 23:07:23 +00:00
return objfile_ap . release ( ) ;
}
}
2010-06-08 16:52:24 +00:00
}
return NULL ;
}
2011-01-15 00:08:44 +00:00
2012-02-05 02:38:54 +00:00
ObjectFile *
2012-02-24 01:59:29 +00:00
ObjectFileELF : : CreateMemoryInstance ( const lldb : : ModuleSP & module_sp ,
DataBufferSP & data_sp ,
const lldb : : ProcessSP & process_sp ,
lldb : : addr_t header_addr )
2012-02-05 02:38:54 +00:00
{
2014-03-05 10:12:43 +00:00
if ( data_sp & & data_sp - > GetByteSize ( ) > ( llvm : : ELF : : EI_NIDENT ) )
{
const uint8_t * magic = data_sp - > GetBytes ( ) ;
if ( ELFHeader : : MagicBytesMatch ( magic ) )
{
unsigned address_size = ELFHeader : : AddressSizeInBytes ( magic ) ;
if ( address_size = = 4 | | address_size = = 8 )
{
std : : auto_ptr < ObjectFileELF > objfile_ap ( new ObjectFileELF ( module_sp , data_sp , process_sp , header_addr ) ) ;
ArchSpec spec ;
if ( objfile_ap - > GetArchitecture ( spec ) & &
objfile_ap - > SetModulesArchitecture ( spec ) )
return objfile_ap . release ( ) ;
}
}
}
2012-02-05 02:38:54 +00:00
return NULL ;
}
2013-05-17 00:20:21 +00:00
bool
ObjectFileELF : : MagicBytesMatch ( DataBufferSP & data_sp ,
lldb : : addr_t data_offset ,
lldb : : addr_t data_length )
{
if ( data_sp & & data_sp - > GetByteSize ( ) > ( llvm : : ELF : : EI_NIDENT + data_offset ) )
{
const uint8_t * magic = data_sp - > GetBytes ( ) + data_offset ;
return ELFHeader : : MagicBytesMatch ( magic ) ;
}
return false ;
}
2012-02-05 02:38:54 +00:00
2013-07-03 01:52:14 +00:00
/*
* crc function from http : //svnweb.freebsd.org/base/head/sys/libkern/crc32.c
*
* COPYRIGHT ( C ) 1986 Gary S . Brown . You may use this program , or
* code or tables extracted from it , as desired without restriction .
*/
static uint32_t
2014-03-25 19:29:09 +00:00
calc_crc32 ( uint32_t crc , const void * buf , size_t size )
2013-07-03 01:52:14 +00:00
{
static const uint32_t g_crc32_tab [ ] =
{
0x00000000 , 0x77073096 , 0xee0e612c , 0x990951ba , 0x076dc419 , 0x706af48f ,
0xe963a535 , 0x9e6495a3 , 0x0edb8832 , 0x79dcb8a4 , 0xe0d5e91e , 0x97d2d988 ,
0x09b64c2b , 0x7eb17cbd , 0xe7b82d07 , 0x90bf1d91 , 0x1db71064 , 0x6ab020f2 ,
0xf3b97148 , 0x84be41de , 0x1adad47d , 0x6ddde4eb , 0xf4d4b551 , 0x83d385c7 ,
0x136c9856 , 0x646ba8c0 , 0xfd62f97a , 0x8a65c9ec , 0x14015c4f , 0x63066cd9 ,
0xfa0f3d63 , 0x8d080df5 , 0x3b6e20c8 , 0x4c69105e , 0xd56041e4 , 0xa2677172 ,
0x3c03e4d1 , 0x4b04d447 , 0xd20d85fd , 0xa50ab56b , 0x35b5a8fa , 0x42b2986c ,
0xdbbbc9d6 , 0xacbcf940 , 0x32d86ce3 , 0x45df5c75 , 0xdcd60dcf , 0xabd13d59 ,
0x26d930ac , 0x51de003a , 0xc8d75180 , 0xbfd06116 , 0x21b4f4b5 , 0x56b3c423 ,
0xcfba9599 , 0xb8bda50f , 0x2802b89e , 0x5f058808 , 0xc60cd9b2 , 0xb10be924 ,
0x2f6f7c87 , 0x58684c11 , 0xc1611dab , 0xb6662d3d , 0x76dc4190 , 0x01db7106 ,
0x98d220bc , 0xefd5102a , 0x71b18589 , 0x06b6b51f , 0x9fbfe4a5 , 0xe8b8d433 ,
0x7807c9a2 , 0x0f00f934 , 0x9609a88e , 0xe10e9818 , 0x7f6a0dbb , 0x086d3d2d ,
0x91646c97 , 0xe6635c01 , 0x6b6b51f4 , 0x1c6c6162 , 0x856530d8 , 0xf262004e ,
0x6c0695ed , 0x1b01a57b , 0x8208f4c1 , 0xf50fc457 , 0x65b0d9c6 , 0x12b7e950 ,
0x8bbeb8ea , 0xfcb9887c , 0x62dd1ddf , 0x15da2d49 , 0x8cd37cf3 , 0xfbd44c65 ,
0x4db26158 , 0x3ab551ce , 0xa3bc0074 , 0xd4bb30e2 , 0x4adfa541 , 0x3dd895d7 ,
0xa4d1c46d , 0xd3d6f4fb , 0x4369e96a , 0x346ed9fc , 0xad678846 , 0xda60b8d0 ,
0x44042d73 , 0x33031de5 , 0xaa0a4c5f , 0xdd0d7cc9 , 0x5005713c , 0x270241aa ,
0xbe0b1010 , 0xc90c2086 , 0x5768b525 , 0x206f85b3 , 0xb966d409 , 0xce61e49f ,
0x5edef90e , 0x29d9c998 , 0xb0d09822 , 0xc7d7a8b4 , 0x59b33d17 , 0x2eb40d81 ,
0xb7bd5c3b , 0xc0ba6cad , 0xedb88320 , 0x9abfb3b6 , 0x03b6e20c , 0x74b1d29a ,
0xead54739 , 0x9dd277af , 0x04db2615 , 0x73dc1683 , 0xe3630b12 , 0x94643b84 ,
0x0d6d6a3e , 0x7a6a5aa8 , 0xe40ecf0b , 0x9309ff9d , 0x0a00ae27 , 0x7d079eb1 ,
0xf00f9344 , 0x8708a3d2 , 0x1e01f268 , 0x6906c2fe , 0xf762575d , 0x806567cb ,
0x196c3671 , 0x6e6b06e7 , 0xfed41b76 , 0x89d32be0 , 0x10da7a5a , 0x67dd4acc ,
0xf9b9df6f , 0x8ebeeff9 , 0x17b7be43 , 0x60b08ed5 , 0xd6d6a3e8 , 0xa1d1937e ,
0x38d8c2c4 , 0x4fdff252 , 0xd1bb67f1 , 0xa6bc5767 , 0x3fb506dd , 0x48b2364b ,
0xd80d2bda , 0xaf0a1b4c , 0x36034af6 , 0x41047a60 , 0xdf60efc3 , 0xa867df55 ,
0x316e8eef , 0x4669be79 , 0xcb61b38c , 0xbc66831a , 0x256fd2a0 , 0x5268e236 ,
0xcc0c7795 , 0xbb0b4703 , 0x220216b9 , 0x5505262f , 0xc5ba3bbe , 0xb2bd0b28 ,
0x2bb45a92 , 0x5cb36a04 , 0xc2d7ffa7 , 0xb5d0cf31 , 0x2cd99e8b , 0x5bdeae1d ,
0x9b64c2b0 , 0xec63f226 , 0x756aa39c , 0x026d930a , 0x9c0906a9 , 0xeb0e363f ,
0x72076785 , 0x05005713 , 0x95bf4a82 , 0xe2b87a14 , 0x7bb12bae , 0x0cb61b38 ,
0x92d28e9b , 0xe5d5be0d , 0x7cdcefb7 , 0x0bdbdf21 , 0x86d3d2d4 , 0xf1d4e242 ,
0x68ddb3f8 , 0x1fda836e , 0x81be16cd , 0xf6b9265b , 0x6fb077e1 , 0x18b74777 ,
0x88085ae6 , 0xff0f6a70 , 0x66063bca , 0x11010b5c , 0x8f659eff , 0xf862ae69 ,
0x616bffd3 , 0x166ccf45 , 0xa00ae278 , 0xd70dd2ee , 0x4e048354 , 0x3903b3c2 ,
0xa7672661 , 0xd06016f7 , 0x4969474d , 0x3e6e77db , 0xaed16a4a , 0xd9d65adc ,
0x40df0b66 , 0x37d83bf0 , 0xa9bcae53 , 0xdebb9ec5 , 0x47b2cf7f , 0x30b5ffe9 ,
0xbdbdf21c , 0xcabac28a , 0x53b39330 , 0x24b4a3a6 , 0xbad03605 , 0xcdd70693 ,
0x54de5729 , 0x23d967bf , 0xb3667a2e , 0xc4614ab8 , 0x5d681b02 , 0x2a6f2b94 ,
0xb40bbe37 , 0xc30c8ea1 , 0x5a05df1b , 0x2d02ef8d
} ;
const uint8_t * p = ( const uint8_t * ) buf ;
2014-03-25 19:29:09 +00:00
crc = crc ^ ~ 0U ;
2013-07-03 01:52:14 +00:00
while ( size - - )
crc = g_crc32_tab [ ( crc ^ * p + + ) & 0xFF ] ^ ( crc > > 8 ) ;
return crc ^ ~ 0U ;
}
2014-03-25 19:29:09 +00:00
static uint32_t
calc_gnu_debuglink_crc32 ( const void * buf , size_t size )
{
return calc_crc32 ( 0U , buf , size ) ;
}
uint32_t
ObjectFileELF : : CalculateELFNotesSegmentsCRC32 ( const ProgramHeaderColl & program_headers ,
DataExtractor & object_data )
{
typedef ProgramHeaderCollConstIter Iter ;
uint32_t core_notes_crc = 0 ;
for ( Iter I = program_headers . begin ( ) ; I ! = program_headers . end ( ) ; + + I )
{
if ( I - > p_type = = llvm : : ELF : : PT_NOTE )
{
const elf_off ph_offset = I - > p_offset ;
const size_t ph_size = I - > p_filesz ;
DataExtractor segment_data ;
if ( segment_data . SetData ( object_data , ph_offset , ph_size ) ! = ph_size )
{
// The ELF program header contained incorrect data,
2014-07-01 21:22:11 +00:00
// probably corefile is incomplete or corrupted.
2014-03-25 19:29:09 +00:00
break ;
}
core_notes_crc = calc_crc32 ( core_notes_crc ,
segment_data . GetDataStart ( ) ,
segment_data . GetByteSize ( ) ) ;
}
}
return core_notes_crc ;
}
2014-06-27 16:52:49 +00:00
static const char *
OSABIAsCString ( unsigned char osabi_byte )
{
# define _MAKE_OSABI_CASE(x) case x: return #x
switch ( osabi_byte )
{
_MAKE_OSABI_CASE ( ELFOSABI_NONE ) ;
_MAKE_OSABI_CASE ( ELFOSABI_HPUX ) ;
_MAKE_OSABI_CASE ( ELFOSABI_NETBSD ) ;
_MAKE_OSABI_CASE ( ELFOSABI_GNU ) ;
_MAKE_OSABI_CASE ( ELFOSABI_HURD ) ;
_MAKE_OSABI_CASE ( ELFOSABI_SOLARIS ) ;
_MAKE_OSABI_CASE ( ELFOSABI_AIX ) ;
_MAKE_OSABI_CASE ( ELFOSABI_IRIX ) ;
_MAKE_OSABI_CASE ( ELFOSABI_FREEBSD ) ;
_MAKE_OSABI_CASE ( ELFOSABI_TRU64 ) ;
_MAKE_OSABI_CASE ( ELFOSABI_MODESTO ) ;
_MAKE_OSABI_CASE ( ELFOSABI_OPENBSD ) ;
_MAKE_OSABI_CASE ( ELFOSABI_OPENVMS ) ;
_MAKE_OSABI_CASE ( ELFOSABI_NSK ) ;
_MAKE_OSABI_CASE ( ELFOSABI_AROS ) ;
_MAKE_OSABI_CASE ( ELFOSABI_FENIXOS ) ;
_MAKE_OSABI_CASE ( ELFOSABI_C6000_ELFABI ) ;
_MAKE_OSABI_CASE ( ELFOSABI_C6000_LINUX ) ;
_MAKE_OSABI_CASE ( ELFOSABI_ARM ) ;
_MAKE_OSABI_CASE ( ELFOSABI_STANDALONE ) ;
default :
return " <unknown-osabi> " ;
}
# undef _MAKE_OSABI_CASE
}
static bool
GetOsFromOSABI ( unsigned char osabi_byte , llvm : : Triple : : OSType & ostype )
{
switch ( osabi_byte )
{
case ELFOSABI_AIX : ostype = llvm : : Triple : : OSType : : AIX ; break ;
case ELFOSABI_FREEBSD : ostype = llvm : : Triple : : OSType : : FreeBSD ; break ;
case ELFOSABI_GNU : ostype = llvm : : Triple : : OSType : : Linux ; break ;
case ELFOSABI_NETBSD : ostype = llvm : : Triple : : OSType : : NetBSD ; break ;
case ELFOSABI_OPENBSD : ostype = llvm : : Triple : : OSType : : OpenBSD ; break ;
case ELFOSABI_SOLARIS : ostype = llvm : : Triple : : OSType : : Solaris ; break ;
default :
ostype = llvm : : Triple : : OSType : : UnknownOS ;
}
return ostype ! = llvm : : Triple : : OSType : : UnknownOS ;
}
2013-04-24 22:29:28 +00:00
size_t
ObjectFileELF : : GetModuleSpecifications ( const lldb_private : : FileSpec & file ,
lldb : : DataBufferSP & data_sp ,
lldb : : offset_t data_offset ,
lldb : : offset_t file_offset ,
lldb : : offset_t length ,
lldb_private : : ModuleSpecList & specs )
{
2014-06-27 16:52:49 +00:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_MODULES ) ) ;
2013-05-17 00:20:21 +00:00
const size_t initial_count = specs . GetSize ( ) ;
2013-05-23 20:57:03 +00:00
2013-05-17 00:20:21 +00:00
if ( ObjectFileELF : : MagicBytesMatch ( data_sp , 0 , data_sp - > GetByteSize ( ) ) )
{
DataExtractor data ;
data . SetData ( data_sp ) ;
elf : : ELFHeader header ;
if ( header . Parse ( data , & data_offset ) )
{
if ( data_sp )
{
2015-03-10 01:15:28 +00:00
ModuleSpec spec ( file ) ;
2014-08-27 12:09:39 +00:00
const uint32_t sub_type = subTypeFromElfHeader ( header ) ;
2013-05-17 00:20:21 +00:00
spec . GetArchitecture ( ) . SetArchitecture ( eArchTypeELF ,
header . e_machine ,
2014-08-27 12:09:39 +00:00
sub_type ) ;
2013-05-17 00:20:21 +00:00
if ( spec . GetArchitecture ( ) . IsValid ( ) )
{
2014-06-27 16:52:49 +00:00
llvm : : Triple : : OSType ostype ;
// First try to determine the OS type from the OSABI field in the elf header.
if ( log )
log - > Printf ( " ObjectFileELF::%s file '%s' module OSABI: %s " , __FUNCTION__ , file . GetPath ( ) . c_str ( ) , OSABIAsCString ( header . e_ident [ EI_OSABI ] ) ) ;
if ( GetOsFromOSABI ( header . e_ident [ EI_OSABI ] , ostype ) & & ostype ! = llvm : : Triple : : OSType : : UnknownOS )
{
spec . GetArchitecture ( ) . GetTriple ( ) . setOS ( ostype ) ;
// Also clear the vendor so we don't end up with situations like
// x86_64-apple-FreeBSD.
spec . GetArchitecture ( ) . GetTriple ( ) . setVendor ( llvm : : Triple : : VendorType : : UnknownVendor ) ;
if ( log )
log - > Printf ( " ObjectFileELF::%s file '%s' set ELF module OS type from ELF header OSABI. " , __FUNCTION__ , file . GetPath ( ) . c_str ( ) ) ;
}
2013-07-01 19:45:50 +00:00
// Try to get the UUID from the section list. Usually that's at the end, so
// map the file in if we don't have it already.
size_t section_header_end = header . e_shoff + header . e_shnum * header . e_shentsize ;
if ( section_header_end > data_sp - > GetByteSize ( ) )
{
2015-02-23 23:47:09 +00:00
data_sp = file . MemoryMapFileContentsIfLocal ( file_offset , section_header_end ) ;
2013-07-01 19:45:50 +00:00
data . SetData ( data_sp ) ;
}
2013-07-03 01:52:14 +00:00
uint32_t gnu_debuglink_crc = 0 ;
2013-07-01 19:45:50 +00:00
std : : string gnu_debuglink_file ;
SectionHeaderColl section_headers ;
2013-07-03 01:52:14 +00:00
lldb_private : : UUID & uuid = spec . GetUUID ( ) ;
2014-06-27 16:52:49 +00:00
GetSectionHeaderInfo ( section_headers , data , header , uuid , gnu_debuglink_file , gnu_debuglink_crc , spec . GetArchitecture ( ) ) ;
// If the module vendor is not set and the module OS matches this host OS, set the module vendor to the host vendor.
llvm : : Triple & spec_triple = spec . GetArchitecture ( ) . GetTriple ( ) ;
if ( spec_triple . getVendor ( ) = = llvm : : Triple : : VendorType : : UnknownVendor )
{
2014-08-20 16:42:51 +00:00
const llvm : : Triple & host_triple = HostInfo : : GetArchitecture ( ) . GetTriple ( ) ;
2014-06-27 16:52:49 +00:00
if ( spec_triple . getOS ( ) = = host_triple . getOS ( ) )
spec_triple . setVendor ( host_triple . getVendor ( ) ) ;
}
if ( log )
log - > Printf ( " ObjectFileELF::%s file '%s' module set to triple: %s (architecture %s) " , __FUNCTION__ , file . GetPath ( ) . c_str ( ) , spec_triple . getTriple ( ) . c_str ( ) , spec . GetArchitecture ( ) . GetArchitectureName ( ) ) ;
2014-03-25 19:29:09 +00:00
2013-07-03 01:52:14 +00:00
if ( ! uuid . IsValid ( ) )
{
2014-03-25 19:29:09 +00:00
uint32_t core_notes_crc = 0 ;
2013-07-03 01:52:14 +00:00
if ( ! gnu_debuglink_crc )
{
2014-03-25 19:29:09 +00:00
lldb_private : : Timer scoped_timer ( __PRETTY_FUNCTION__ ,
" Calculating module crc32 %s with size % " PRIu64 " KiB " ,
file . GetLastPathComponent ( ) . AsCString ( ) ,
( file . GetByteSize ( ) - file_offset ) / 1024 ) ;
// For core files - which usually don't happen to have a gnu_debuglink,
2014-07-01 21:22:11 +00:00
// and are pretty bulky - calculating whole contents crc32 would be too much of luxury.
2014-03-25 19:29:09 +00:00
// Thus we will need to fallback to something simpler.
if ( header . e_type = = llvm : : ELF : : ET_CORE )
{
size_t program_headers_end = header . e_phoff + header . e_phnum * header . e_phentsize ;
if ( program_headers_end > data_sp - > GetByteSize ( ) )
{
2015-02-23 23:47:09 +00:00
data_sp = file . MemoryMapFileContentsIfLocal ( file_offset , program_headers_end ) ;
2014-03-25 19:29:09 +00:00
data . SetData ( data_sp ) ;
}
ProgramHeaderColl program_headers ;
GetProgramHeaderInfo ( program_headers , data , header ) ;
size_t segment_data_end = 0 ;
for ( ProgramHeaderCollConstIter I = program_headers . begin ( ) ;
I ! = program_headers . end ( ) ; + + I )
{
2014-03-25 20:53:33 +00:00
segment_data_end = std : : max < unsigned long long > ( I - > p_offset + I - > p_filesz , segment_data_end ) ;
2014-03-25 19:29:09 +00:00
}
if ( segment_data_end > data_sp - > GetByteSize ( ) )
{
2015-02-23 23:47:09 +00:00
data_sp = file . MemoryMapFileContentsIfLocal ( file_offset , segment_data_end ) ;
2014-03-25 19:29:09 +00:00
data . SetData ( data_sp ) ;
}
core_notes_crc = CalculateELFNotesSegmentsCRC32 ( program_headers , data ) ;
}
else
{
// Need to map entire file into memory to calculate the crc.
2015-02-23 23:47:09 +00:00
data_sp = file . MemoryMapFileContentsIfLocal ( file_offset , SIZE_MAX ) ;
2014-03-25 19:29:09 +00:00
data . SetData ( data_sp ) ;
gnu_debuglink_crc = calc_gnu_debuglink_crc32 ( data . GetDataStart ( ) , data . GetByteSize ( ) ) ;
}
2013-07-03 01:52:14 +00:00
}
if ( gnu_debuglink_crc )
{
// Use 4 bytes of crc from the .gnu_debuglink section.
uint32_t uuidt [ 4 ] = { gnu_debuglink_crc , 0 , 0 , 0 } ;
uuid . SetBytes ( uuidt , sizeof ( uuidt ) ) ;
}
2014-03-25 19:29:09 +00:00
else if ( core_notes_crc )
{
// Use 8 bytes - first 4 bytes for *magic* prefix, mainly to make it look different form
// .gnu_debuglink crc followed by 4 bytes of note segments crc.
uint32_t uuidt [ 4 ] = { g_core_uuid_magic , core_notes_crc , 0 , 0 } ;
uuid . SetBytes ( uuidt , sizeof ( uuidt ) ) ;
}
2013-07-03 01:52:14 +00:00
}
2013-07-01 19:45:50 +00:00
2013-05-17 00:20:21 +00:00
specs . Append ( spec ) ;
}
}
}
}
2013-05-23 20:57:03 +00:00
2013-05-17 00:20:21 +00:00
return specs . GetSize ( ) - initial_count ;
2013-04-24 22:29:28 +00:00
}
2010-07-13 23:07:23 +00:00
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
2013-05-10 21:47:16 +00:00
lldb_private : : ConstString
2010-07-13 23:07:23 +00:00
ObjectFileELF : : GetPluginName ( )
{
return GetPluginNameStatic ( ) ;
}
uint32_t
ObjectFileELF : : GetPluginVersion ( )
{
return m_plugin_version ;
}
//------------------------------------------------------------------
// ObjectFile protocol
//------------------------------------------------------------------
2010-06-08 16:52:24 +00:00
2012-02-24 01:59:29 +00:00
ObjectFileELF : : ObjectFileELF ( const lldb : : ModuleSP & module_sp ,
2013-02-06 17:22:03 +00:00
DataBufferSP & data_sp ,
lldb : : offset_t data_offset ,
2012-02-24 01:59:29 +00:00
const FileSpec * file ,
2013-02-06 17:22:03 +00:00
lldb : : offset_t file_offset ,
lldb : : offset_t length ) :
ObjectFile ( module_sp , file , file_offset , length , data_sp , data_offset ) ,
2012-02-24 01:59:29 +00:00
m_header ( ) ,
2014-06-27 16:52:49 +00:00
m_uuid ( ) ,
m_gnu_debuglink_file ( ) ,
m_gnu_debuglink_crc ( 0 ) ,
2012-02-24 01:59:29 +00:00
m_program_headers ( ) ,
m_section_headers ( ) ,
2014-06-27 16:52:49 +00:00
m_dynamic_symbols ( ) ,
m_filespec_ap ( ) ,
m_entry_point_address ( ) ,
m_arch_spec ( )
2010-06-08 16:52:24 +00:00
{
if ( file )
m_file = * file ;
2010-07-13 23:07:23 +00:00
: : memset ( & m_header , 0 , sizeof ( m_header ) ) ;
2010-06-08 16:52:24 +00:00
}
2014-03-05 10:12:43 +00:00
ObjectFileELF : : ObjectFileELF ( const lldb : : ModuleSP & module_sp ,
DataBufferSP & data_sp ,
const lldb : : ProcessSP & process_sp ,
addr_t header_addr ) :
ObjectFile ( module_sp , process_sp , LLDB_INVALID_ADDRESS , data_sp ) ,
m_header ( ) ,
2014-06-27 16:52:49 +00:00
m_uuid ( ) ,
m_gnu_debuglink_file ( ) ,
m_gnu_debuglink_crc ( 0 ) ,
2014-03-05 10:12:43 +00:00
m_program_headers ( ) ,
m_section_headers ( ) ,
2014-06-27 16:52:49 +00:00
m_dynamic_symbols ( ) ,
m_filespec_ap ( ) ,
m_entry_point_address ( ) ,
m_arch_spec ( )
2014-03-05 10:12:43 +00:00
{
: : memset ( & m_header , 0 , sizeof ( m_header ) ) ;
}
2010-06-08 16:52:24 +00:00
ObjectFileELF : : ~ ObjectFileELF ( )
{
}
2010-08-09 23:31:02 +00:00
bool
ObjectFileELF : : IsExecutable ( ) const
{
2014-07-22 12:01:43 +00:00
return ( ( m_header . e_type & ET_EXEC ) ! = 0 ) | | ( m_header . e_entry ! = 0 ) ;
2010-08-09 23:31:02 +00:00
}
2014-02-06 19:02:19 +00:00
bool
2014-02-07 22:54:47 +00:00
ObjectFileELF : : SetLoadAddress ( Target & target ,
lldb : : addr_t value ,
bool value_is_offset )
2014-02-06 19:02:19 +00:00
{
ModuleSP module_sp = GetModule ( ) ;
if ( module_sp )
{
size_t num_loaded_sections = 0 ;
SectionList * section_list = GetSectionList ( ) ;
if ( section_list )
{
2014-02-07 22:54:47 +00:00
if ( value_is_offset )
2014-02-06 19:02:19 +00:00
{
2014-02-07 22:54:47 +00:00
const size_t num_sections = section_list - > GetSize ( ) ;
size_t sect_idx = 0 ;
2014-02-21 18:08:09 +00:00
2014-02-07 22:54:47 +00:00
for ( sect_idx = 0 ; sect_idx < num_sections ; + + sect_idx )
2014-02-06 19:02:19 +00:00
{
2014-02-07 22:54:47 +00:00
// Iterate through the object file sections to find all
// of the sections that have SHF_ALLOC in their flag bits.
SectionSP section_sp ( section_list - > GetSectionAtIndex ( sect_idx ) ) ;
// if (section_sp && !section_sp->IsThreadSpecific())
if ( section_sp & & section_sp - > Test ( SHF_ALLOC ) )
{
if ( target . GetSectionLoadList ( ) . SetSectionLoadAddress ( section_sp , section_sp - > GetFileAddress ( ) + value ) )
+ + num_loaded_sections ;
}
2014-02-06 19:02:19 +00:00
}
2014-02-07 22:54:47 +00:00
return num_loaded_sections > 0 ;
}
else
{
// Not sure how to slide an ELF file given the base address
// of the ELF file in memory
2014-02-06 19:02:19 +00:00
}
}
}
2014-02-21 18:08:09 +00:00
return false ; // If it changed
2014-02-06 19:02:19 +00:00
}
2010-06-08 16:52:24 +00:00
ByteOrder
2010-07-13 23:07:23 +00:00
ObjectFileELF : : GetByteOrder ( ) const
2010-06-08 16:52:24 +00:00
{
if ( m_header . e_ident [ EI_DATA ] = = ELFDATA2MSB )
return eByteOrderBig ;
if ( m_header . e_ident [ EI_DATA ] = = ELFDATA2LSB )
return eByteOrderLittle ;
return eByteOrderInvalid ;
}
2013-01-25 18:06:21 +00:00
uint32_t
2010-07-13 23:07:23 +00:00
ObjectFileELF : : GetAddressByteSize ( ) const
2010-06-08 16:52:24 +00:00
{
return m_data . GetAddressByteSize ( ) ;
}
2014-09-15 22:33:39 +00:00
// Top 16 bits of the `Symbol` flags are available.
# define ARM_ELF_SYM_IS_THUMB (1 << 16)
AddressClass
ObjectFileELF : : GetAddressClass ( addr_t file_addr )
{
auto res = ObjectFile : : GetAddressClass ( file_addr ) ;
if ( res ! = eAddressClassCode )
return res ;
ArchSpec arch_spec ;
GetArchitecture ( arch_spec ) ;
if ( arch_spec . GetMachine ( ) ! = llvm : : Triple : : arm )
return res ;
auto symtab = GetSymtab ( ) ;
if ( symtab = = nullptr )
return res ;
auto symbol = symtab - > FindSymbolContainingFileAddress ( file_addr ) ;
if ( symbol = = nullptr )
return res ;
// Thumb symbols have the lower bit set in the flags field so we just check
// for that.
if ( symbol - > GetFlags ( ) & ARM_ELF_SYM_IS_THUMB )
res = eAddressClassCodeAlternateISA ;
return res ;
}
2013-01-25 18:06:21 +00:00
size_t
2010-07-13 23:07:23 +00:00
ObjectFileELF : : SectionIndex ( const SectionHeaderCollIter & I )
2010-06-08 16:52:24 +00:00
{
2013-01-25 18:06:21 +00:00
return std : : distance ( m_section_headers . begin ( ) , I ) + 1u ;
2010-07-13 23:07:23 +00:00
}
2010-06-08 16:52:24 +00:00
2013-01-25 18:06:21 +00:00
size_t
2010-07-13 23:07:23 +00:00
ObjectFileELF : : SectionIndex ( const SectionHeaderCollConstIter & I ) const
{
2013-01-25 18:06:21 +00:00
return std : : distance ( m_section_headers . begin ( ) , I ) + 1u ;
2010-07-13 23:07:23 +00:00
}
2010-06-08 16:52:24 +00:00
2010-07-13 23:07:23 +00:00
bool
ObjectFileELF : : ParseHeader ( )
{
2013-05-16 23:29:36 +00:00
lldb : : offset_t offset = 0 ;
2010-07-13 23:07:23 +00:00
return m_header . Parse ( m_data , & offset ) ;
2010-06-08 16:52:24 +00:00
}
bool
2011-02-04 18:53:10 +00:00
ObjectFileELF : : GetUUID ( lldb_private : : UUID * uuid )
2010-06-08 16:52:24 +00:00
{
2013-07-01 19:45:50 +00:00
// Need to parse the section list to get the UUIDs, so make sure that's been done.
2014-03-25 19:29:09 +00:00
if ( ! ParseSectionHeaders ( ) & & GetType ( ) ! = ObjectFile : : eTypeCoreFile )
2013-07-01 19:45:50 +00:00
return false ;
2013-05-23 20:57:03 +00:00
if ( m_uuid . IsValid ( ) )
{
2013-07-01 19:45:50 +00:00
// We have the full build id uuid.
2013-05-23 20:57:03 +00:00
* uuid = m_uuid ;
return true ;
}
2014-03-25 19:29:09 +00:00
else if ( GetType ( ) = = ObjectFile : : eTypeCoreFile )
{
uint32_t core_notes_crc = 0 ;
if ( ! ParseProgramHeaders ( ) )
return false ;
core_notes_crc = CalculateELFNotesSegmentsCRC32 ( m_program_headers , m_data ) ;
if ( core_notes_crc )
{
// Use 8 bytes - first 4 bytes for *magic* prefix, mainly to make it
// look different form .gnu_debuglink crc - followed by 4 bytes of note
// segments crc.
uint32_t uuidt [ 4 ] = { g_core_uuid_magic , core_notes_crc , 0 , 0 } ;
m_uuid . SetBytes ( uuidt , sizeof ( uuidt ) ) ;
}
}
else
2013-07-01 19:45:50 +00:00
{
2013-07-03 01:52:14 +00:00
if ( ! m_gnu_debuglink_crc )
m_gnu_debuglink_crc = calc_gnu_debuglink_crc32 ( m_data . GetDataStart ( ) , m_data . GetByteSize ( ) ) ;
2013-07-01 19:45:50 +00:00
if ( m_gnu_debuglink_crc )
{
// Use 4 bytes of crc from the .gnu_debuglink section.
uint32_t uuidt [ 4 ] = { m_gnu_debuglink_crc , 0 , 0 , 0 } ;
2014-03-25 19:29:09 +00:00
m_uuid . SetBytes ( uuidt , sizeof ( uuidt ) ) ;
2013-07-01 19:45:50 +00:00
}
}
2014-03-25 19:29:09 +00:00
if ( m_uuid . IsValid ( ) )
{
* uuid = m_uuid ;
return true ;
}
2010-06-08 16:52:24 +00:00
return false ;
}
2013-07-01 19:45:50 +00:00
lldb_private : : FileSpecList
ObjectFileELF : : GetDebugSymbolFilePaths ( )
{
FileSpecList file_spec_list ;
if ( ! m_gnu_debuglink_file . empty ( ) )
{
FileSpec file_spec ( m_gnu_debuglink_file . c_str ( ) , false ) ;
file_spec_list . Append ( file_spec ) ;
}
return file_spec_list ;
}
2010-06-08 16:52:24 +00:00
uint32_t
2010-07-13 23:07:23 +00:00
ObjectFileELF : : GetDependentModules ( FileSpecList & files )
2010-06-08 16:52:24 +00:00
{
2010-07-13 23:07:23 +00:00
size_t num_modules = ParseDependentModules ( ) ;
uint32_t num_specs = 0 ;
for ( unsigned i = 0 ; i < num_modules ; + + i )
{
if ( files . AppendIfUnique ( m_filespec_ap - > GetFileSpecAtIndex ( i ) ) )
num_specs + + ;
}
return num_specs ;
}
2011-03-30 16:07:05 +00:00
Address
2013-10-11 17:39:07 +00:00
ObjectFileELF : : GetImageInfoAddress ( Target * target )
2011-03-30 16:07:05 +00:00
{
if ( ! ParseDynamicSymbols ( ) )
2011-01-15 00:08:44 +00:00
return Address ( ) ;
SectionList * section_list = GetSectionList ( ) ;
if ( ! section_list )
return Address ( ) ;
2013-07-10 01:23:25 +00:00
// Find the SHT_DYNAMIC (.dynamic) section.
SectionSP dynsym_section_sp ( section_list - > FindSectionByType ( eSectionTypeELFDynamicLinkInfo , true ) ) ;
if ( ! dynsym_section_sp )
2011-03-30 16:07:05 +00:00
return Address ( ) ;
2013-07-10 01:23:25 +00:00
assert ( dynsym_section_sp - > GetObjectFile ( ) = = this ) ;
2011-03-30 16:07:05 +00:00
2013-07-10 01:23:25 +00:00
user_id_t dynsym_id = dynsym_section_sp - > GetID ( ) ;
2013-07-01 19:45:50 +00:00
const ELFSectionHeaderInfo * dynsym_hdr = GetSectionHeaderByIndex ( dynsym_id ) ;
2011-03-30 16:07:05 +00:00
if ( ! dynsym_hdr )
return Address ( ) ;
2013-07-10 01:23:25 +00:00
for ( size_t i = 0 ; i < m_dynamic_symbols . size ( ) ; + + i )
2011-01-15 00:08:44 +00:00
{
2013-07-10 01:23:25 +00:00
ELFDynamic & symbol = m_dynamic_symbols [ i ] ;
2012-02-24 01:59:29 +00:00
2013-10-11 17:39:07 +00:00
if ( symbol . d_tag = = DT_DEBUG )
2013-07-10 01:23:25 +00:00
{
// Compute the offset as the number of previous entries plus the
// size of d_tag.
addr_t offset = i * dynsym_hdr - > sh_entsize + GetAddressByteSize ( ) ;
return Address ( dynsym_section_sp , offset ) ;
2011-01-15 00:08:44 +00:00
}
2013-10-11 17:39:07 +00:00
else if ( symbol . d_tag = = DT_MIPS_RLD_MAP & & target )
{
addr_t offset = i * dynsym_hdr - > sh_entsize + GetAddressByteSize ( ) ;
addr_t dyn_base = dynsym_section_sp - > GetLoadBaseAddress ( target ) ;
if ( dyn_base = = LLDB_INVALID_ADDRESS )
return Address ( ) ;
Address addr ;
Error error ;
if ( target - > ReadPointerFromMemory ( dyn_base + offset , false , error , addr ) )
return addr ;
}
2011-01-15 00:08:44 +00:00
}
return Address ( ) ;
}
2011-03-07 23:44:08 +00:00
lldb_private : : Address
ObjectFileELF : : GetEntryPointAddress ( )
{
2011-03-08 04:12:15 +00:00
if ( m_entry_point_address . IsValid ( ) )
2011-03-07 23:44:08 +00:00
return m_entry_point_address ;
2011-03-08 04:12:15 +00:00
if ( ! ParseHeader ( ) | | ! IsExecutable ( ) )
2011-03-07 23:44:08 +00:00
return m_entry_point_address ;
2013-07-10 01:23:25 +00:00
SectionList * section_list = GetSectionList ( ) ;
addr_t offset = m_header . e_entry ;
2011-03-08 04:12:15 +00:00
2013-07-10 01:23:25 +00:00
if ( ! section_list )
2011-03-08 04:12:15 +00:00
m_entry_point_address . SetOffset ( offset ) ;
2013-07-10 01:23:25 +00:00
else
m_entry_point_address . ResolveAddressUsingFileSections ( offset , section_list ) ;
2011-03-08 04:12:15 +00:00
return m_entry_point_address ;
2011-03-07 23:44:08 +00:00
}
2010-07-13 23:07:23 +00:00
//----------------------------------------------------------------------
// ParseDependentModules
//----------------------------------------------------------------------
size_t
ObjectFileELF : : ParseDependentModules ( )
{
if ( m_filespec_ap . get ( ) )
return m_filespec_ap - > GetSize ( ) ;
m_filespec_ap . reset ( new FileSpecList ( ) ) ;
2013-07-01 19:45:50 +00:00
if ( ! ParseSectionHeaders ( ) )
2010-07-13 23:07:23 +00:00
return 0 ;
SectionList * section_list = GetSectionList ( ) ;
if ( ! section_list )
return 0 ;
2013-07-10 01:23:25 +00:00
// Find the SHT_DYNAMIC section.
Section * dynsym = section_list - > FindSectionByType ( eSectionTypeELFDynamicLinkInfo , true ) . get ( ) ;
if ( ! dynsym )
return 0 ;
assert ( dynsym - > GetObjectFile ( ) = = this ) ;
const ELFSectionHeaderInfo * header = GetSectionHeaderByIndex ( dynsym - > GetID ( ) ) ;
if ( ! header )
return 0 ;
// sh_link: section header index of string table used by entries in the section.
Section * dynstr = section_list - > FindSectionByID ( header - > sh_link + 1 ) . get ( ) ;
if ( ! dynstr )
2010-07-13 23:07:23 +00:00
return 0 ;
DataExtractor dynsym_data ;
DataExtractor dynstr_data ;
2012-02-05 02:38:54 +00:00
if ( ReadSectionData ( dynsym , dynsym_data ) & &
ReadSectionData ( dynstr , dynstr_data ) )
2010-07-13 23:07:23 +00:00
{
ELFDynamic symbol ;
2013-01-25 18:06:21 +00:00
const lldb : : offset_t section_size = dynsym_data . GetByteSize ( ) ;
lldb : : offset_t offset = 0 ;
2010-07-13 23:07:23 +00:00
// The only type of entries we are concerned with are tagged DT_NEEDED,
// yielding the name of a required library.
while ( offset < section_size )
{
if ( ! symbol . Parse ( dynsym_data , & offset ) )
break ;
if ( symbol . d_tag ! = DT_NEEDED )
continue ;
uint32_t str_index = static_cast < uint32_t > ( symbol . d_val ) ;
const char * lib_name = dynstr_data . PeekCStr ( str_index ) ;
2010-10-20 20:54:39 +00:00
m_filespec_ap - > Append ( FileSpec ( lib_name , true ) ) ;
2010-07-13 23:07:23 +00:00
}
}
return m_filespec_ap - > GetSize ( ) ;
2010-06-08 16:52:24 +00:00
}
//----------------------------------------------------------------------
2014-03-25 19:29:09 +00:00
// GetProgramHeaderInfo
2010-06-08 16:52:24 +00:00
//----------------------------------------------------------------------
size_t
2014-03-25 19:29:09 +00:00
ObjectFileELF : : GetProgramHeaderInfo ( ProgramHeaderColl & program_headers ,
DataExtractor & object_data ,
const ELFHeader & header )
2010-06-08 16:52:24 +00:00
{
// We have already parsed the program headers
2014-03-25 19:29:09 +00:00
if ( ! program_headers . empty ( ) )
return program_headers . size ( ) ;
2010-06-08 16:52:24 +00:00
2010-07-13 23:07:23 +00:00
// If there are no program headers to read we are done.
2014-03-25 19:29:09 +00:00
if ( header . e_phnum = = 0 )
2010-07-13 23:07:23 +00:00
return 0 ;
2010-06-08 16:52:24 +00:00
2014-03-25 19:29:09 +00:00
program_headers . resize ( header . e_phnum ) ;
if ( program_headers . size ( ) ! = header . e_phnum )
2010-07-13 23:07:23 +00:00
return 0 ;
2010-06-08 16:52:24 +00:00
2014-03-25 19:29:09 +00:00
const size_t ph_size = header . e_phnum * header . e_phentsize ;
const elf_off ph_offset = header . e_phoff ;
2012-01-12 05:25:17 +00:00
DataExtractor data ;
2014-03-25 19:29:09 +00:00
if ( data . SetData ( object_data , ph_offset , ph_size ) ! = ph_size )
2010-07-13 23:07:23 +00:00
return 0 ;
2010-06-08 16:52:24 +00:00
2010-07-13 23:07:23 +00:00
uint32_t idx ;
2013-01-25 18:06:21 +00:00
lldb : : offset_t offset ;
2014-03-25 19:29:09 +00:00
for ( idx = 0 , offset = 0 ; idx < header . e_phnum ; + + idx )
2010-07-13 23:07:23 +00:00
{
2014-03-25 19:29:09 +00:00
if ( program_headers [ idx ] . Parse ( data , & offset ) = = false )
2010-07-13 23:07:23 +00:00
break ;
2010-06-08 16:52:24 +00:00
}
2014-03-25 19:29:09 +00:00
if ( idx < program_headers . size ( ) )
program_headers . resize ( idx ) ;
return program_headers . size ( ) ;
}
2010-07-13 23:07:23 +00:00
2014-03-25 19:29:09 +00:00
//----------------------------------------------------------------------
// ParseProgramHeaders
//----------------------------------------------------------------------
size_t
ObjectFileELF : : ParseProgramHeaders ( )
{
return GetProgramHeaderInfo ( m_program_headers , m_data , m_header ) ;
2010-06-08 16:52:24 +00:00
}
2014-06-27 16:52:49 +00:00
lldb_private : : Error
ObjectFileELF : : RefineModuleDetailsFromNote ( lldb_private : : DataExtractor & data , lldb_private : : ArchSpec & arch_spec , lldb_private : : UUID & uuid )
2013-07-01 19:45:50 +00:00
{
2014-06-27 16:52:49 +00:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_MODULES ) ) ;
Error error ;
2013-07-01 19:45:50 +00:00
lldb : : offset_t offset = 0 ;
while ( true )
{
2014-06-27 16:52:49 +00:00
// Parse the note header. If this fails, bail out.
2013-12-02 17:49:13 +00:00
ELFNote note = ELFNote ( ) ;
if ( ! note . Parse ( data , & offset ) )
2014-06-27 16:52:49 +00:00
{
// We're done.
return error ;
}
// If a tag processor handles the tag, it should set processed to true, and
// the loop will assume the tag processing has moved entirely past the note's payload.
// Otherwise, leave it false and the end of the loop will handle the offset properly.
bool processed = false ;
if ( log )
log - > Printf ( " ObjectFileELF::%s parsing note name='%s', type=% " PRIu32 , __FUNCTION__ , note . n_name . c_str ( ) , note . n_type ) ;
2013-07-01 19:45:50 +00:00
2014-06-27 16:52:49 +00:00
// Process FreeBSD ELF notes.
if ( ( note . n_name = = LLDB_NT_OWNER_FREEBSD ) & &
( note . n_type = = LLDB_NT_FREEBSD_ABI_TAG ) & &
( note . n_descsz = = LLDB_NT_FREEBSD_ABI_SIZE ) )
2013-07-01 19:45:50 +00:00
{
2014-06-27 16:52:49 +00:00
// We'll consume the payload below.
processed = true ;
// Pull out the min version info.
uint32_t version_info ;
if ( data . GetU32 ( & offset , & version_info , 1 ) = = nullptr )
{
error . SetErrorString ( " failed to read FreeBSD ABI note payload " ) ;
return error ;
}
// Convert the version info into a major/minor number.
const uint32_t version_major = version_info / 100000 ;
const uint32_t version_minor = ( version_info / 1000 ) % 100 ;
char os_name [ 32 ] ;
snprintf ( os_name , sizeof ( os_name ) , " freebsd% " PRIu32 " .% " PRIu32 , version_major , version_minor ) ;
// Set the elf OS version to FreeBSD. Also clear the vendor.
arch_spec . GetTriple ( ) . setOSName ( os_name ) ;
arch_spec . GetTriple ( ) . setVendor ( llvm : : Triple : : VendorType : : UnknownVendor ) ;
if ( log )
log - > Printf ( " ObjectFileELF::%s detected FreeBSD % " PRIu32 " .% " PRIu32 " .% " PRIu32 , __FUNCTION__ , version_major , version_minor , static_cast < uint32_t > ( version_info % 1000 ) ) ;
}
// Process GNU ELF notes.
else if ( note . n_name = = LLDB_NT_OWNER_GNU )
{
switch ( note . n_type )
{
case LLDB_NT_GNU_ABI_TAG :
if ( note . n_descsz = = LLDB_NT_GNU_ABI_SIZE )
{
// We'll consume the payload below.
processed = true ;
// Pull out the min OS version supporting the ABI.
uint32_t version_info [ 4 ] ;
if ( data . GetU32 ( & offset , & version_info [ 0 ] , note . n_descsz / 4 ) = = nullptr )
{
error . SetErrorString ( " failed to read GNU ABI note payload " ) ;
return error ;
}
// Set the OS per the OS field.
switch ( version_info [ 0 ] )
{
case LLDB_NT_GNU_ABI_OS_LINUX :
arch_spec . GetTriple ( ) . setOS ( llvm : : Triple : : OSType : : Linux ) ;
arch_spec . GetTriple ( ) . setVendor ( llvm : : Triple : : VendorType : : UnknownVendor ) ;
if ( log )
log - > Printf ( " ObjectFileELF::%s detected Linux, min version % " PRIu32 " .% " PRIu32 " .% " PRIu32 , __FUNCTION__ , version_info [ 1 ] , version_info [ 2 ] , version_info [ 3 ] ) ;
// FIXME we have the minimal version number, we could be propagating that. version_info[1] = OS Major, version_info[2] = OS Minor, version_info[3] = Revision.
break ;
case LLDB_NT_GNU_ABI_OS_HURD :
arch_spec . GetTriple ( ) . setOS ( llvm : : Triple : : OSType : : UnknownOS ) ;
arch_spec . GetTriple ( ) . setVendor ( llvm : : Triple : : VendorType : : UnknownVendor ) ;
if ( log )
log - > Printf ( " ObjectFileELF::%s detected Hurd (unsupported), min version % " PRIu32 " .% " PRIu32 " .% " PRIu32 , __FUNCTION__ , version_info [ 1 ] , version_info [ 2 ] , version_info [ 3 ] ) ;
break ;
case LLDB_NT_GNU_ABI_OS_SOLARIS :
arch_spec . GetTriple ( ) . setOS ( llvm : : Triple : : OSType : : Solaris ) ;
arch_spec . GetTriple ( ) . setVendor ( llvm : : Triple : : VendorType : : UnknownVendor ) ;
if ( log )
log - > Printf ( " ObjectFileELF::%s detected Solaris, min version % " PRIu32 " .% " PRIu32 " .% " PRIu32 , __FUNCTION__ , version_info [ 1 ] , version_info [ 2 ] , version_info [ 3 ] ) ;
break ;
default :
if ( log )
log - > Printf ( " ObjectFileELF::%s unrecognized OS in note, id % " PRIu32 " , min version % " PRIu32 " .% " PRIu32 " .% " PRIu32 , __FUNCTION__ , version_info [ 0 ] , version_info [ 1 ] , version_info [ 2 ] , version_info [ 3 ] ) ;
break ;
}
}
break ;
case LLDB_NT_GNU_BUILD_ID_TAG :
// Only bother processing this if we don't already have the uuid set.
if ( ! uuid . IsValid ( ) )
{
// We'll consume the payload below.
processed = true ;
// 16 bytes is UUID|MD5, 20 bytes is SHA1
if ( ( note . n_descsz = = 16 | | note . n_descsz = = 20 ) )
{
uint8_t uuidbuf [ 20 ] ;
if ( data . GetU8 ( & offset , & uuidbuf , note . n_descsz ) = = nullptr )
{
error . SetErrorString ( " failed to read GNU_BUILD_ID note payload " ) ;
return error ;
}
// Save the build id as the UUID for the module.
uuid . SetBytes ( uuidbuf , note . n_descsz ) ;
}
}
break ;
}
}
// Process NetBSD ELF notes.
else if ( ( note . n_name = = LLDB_NT_OWNER_NETBSD ) & &
( note . n_type = = LLDB_NT_NETBSD_ABI_TAG ) & &
( note . n_descsz = = LLDB_NT_NETBSD_ABI_SIZE ) )
{
// We'll consume the payload below.
processed = true ;
// Pull out the min version info.
uint32_t version_info ;
if ( data . GetU32 ( & offset , & version_info , 1 ) = = nullptr )
{
error . SetErrorString ( " failed to read NetBSD ABI note payload " ) ;
return error ;
}
// Set the elf OS version to NetBSD. Also clear the vendor.
arch_spec . GetTriple ( ) . setOS ( llvm : : Triple : : OSType : : NetBSD ) ;
arch_spec . GetTriple ( ) . setVendor ( llvm : : Triple : : VendorType : : UnknownVendor ) ;
if ( log )
log - > Printf ( " ObjectFileELF::%s detected NetBSD, min version constant % " PRIu32 , __FUNCTION__ , version_info ) ;
2013-07-01 19:45:50 +00:00
}
2014-07-16 15:03:10 +00:00
// Process CSR kalimba notes
else if ( ( note . n_type = = LLDB_NT_GNU_ABI_TAG ) & &
( note . n_name = = LLDB_NT_OWNER_CSR ) )
{
// We'll consume the payload below.
processed = true ;
arch_spec . GetTriple ( ) . setOS ( llvm : : Triple : : OSType : : UnknownOS ) ;
arch_spec . GetTriple ( ) . setVendor ( llvm : : Triple : : VendorType : : CSR ) ;
// TODO At some point the description string could be processed.
// It could provide a steer towards the kalimba variant which
// this ELF targets.
if ( note . n_descsz )
{
const char * cstr = data . GetCStr ( & offset , llvm : : RoundUpToAlignment ( note . n_descsz , 4 ) ) ;
( void ) cstr ;
}
}
2015-03-18 10:36:27 +00:00
else if ( note . n_name = = LLDB_NT_OWNER_ANDROID )
{
arch_spec . GetTriple ( ) . setOS ( llvm : : Triple : : OSType : : Linux ) ;
arch_spec . GetTriple ( ) . setEnvironment ( llvm : : Triple : : EnvironmentType : : Android ) ;
}
2014-06-27 16:52:49 +00:00
if ( ! processed )
offset + = llvm : : RoundUpToAlignment ( note . n_descsz , 4 ) ;
2013-07-01 19:45:50 +00:00
}
2014-06-27 16:52:49 +00:00
return error ;
2013-07-01 19:45:50 +00:00
}
2014-06-27 16:52:49 +00:00
2010-06-08 16:52:24 +00:00
//----------------------------------------------------------------------
2013-07-01 19:45:50 +00:00
// GetSectionHeaderInfo
2010-06-08 16:52:24 +00:00
//----------------------------------------------------------------------
size_t
2013-07-01 19:45:50 +00:00
ObjectFileELF : : GetSectionHeaderInfo ( SectionHeaderColl & section_headers ,
lldb_private : : DataExtractor & object_data ,
const elf : : ELFHeader & header ,
lldb_private : : UUID & uuid ,
std : : string & gnu_debuglink_file ,
2014-06-27 16:52:49 +00:00
uint32_t & gnu_debuglink_crc ,
ArchSpec & arch_spec )
2010-06-08 16:52:24 +00:00
{
2014-07-11 15:13:33 +00:00
// Don't reparse the section headers if we already did that.
if ( ! section_headers . empty ( ) )
return section_headers . size ( ) ;
2014-07-01 21:22:11 +00:00
// Only initialize the arch_spec to okay defaults if they're not already set.
2014-06-27 16:52:49 +00:00
// We'll refine this with note data as we parse the notes.
if ( arch_spec . GetTriple ( ) . getOS ( ) = = llvm : : Triple : : OSType : : UnknownOS )
{
2014-08-27 12:09:39 +00:00
const uint32_t sub_type = subTypeFromElfHeader ( header ) ;
arch_spec . SetArchitecture ( eArchTypeELF , header . e_machine , sub_type ) ;
2014-07-12 00:11:34 +00:00
switch ( arch_spec . GetAddressByteSize ( ) )
{
case 4 :
{
2014-08-20 16:42:51 +00:00
const ArchSpec host_arch32 = HostInfo : : GetArchitecture ( HostInfo : : eArchKind32 ) ;
2014-07-12 00:11:34 +00:00
if ( host_arch32 . GetCore ( ) = = arch_spec . GetCore ( ) )
{
2014-08-19 17:18:29 +00:00
arch_spec . GetTriple ( ) . setOSName ( HostInfo : : GetOSString ( ) . data ( ) ) ;
arch_spec . GetTriple ( ) . setVendorName ( HostInfo : : GetVendorString ( ) . data ( ) ) ;
2014-07-12 00:11:34 +00:00
}
}
break ;
case 8 :
{
2014-08-20 16:42:51 +00:00
const ArchSpec host_arch64 = HostInfo : : GetArchitecture ( HostInfo : : eArchKind64 ) ;
2014-07-12 00:11:34 +00:00
if ( host_arch64 . GetCore ( ) = = arch_spec . GetCore ( ) )
{
2014-08-19 17:18:29 +00:00
arch_spec . GetTriple ( ) . setOSName ( HostInfo : : GetOSString ( ) . data ( ) ) ;
arch_spec . GetTriple ( ) . setVendorName ( HostInfo : : GetVendorString ( ) . data ( ) ) ;
2014-07-12 00:11:34 +00:00
}
}
break ;
}
2014-06-27 16:52:49 +00:00
}
2010-07-13 23:07:23 +00:00
// If there are no section headers we are done.
2013-07-01 19:45:50 +00:00
if ( header . e_shnum = = 0 )
2010-07-13 23:07:23 +00:00
return 0 ;
2010-06-08 16:52:24 +00:00
2014-06-27 16:52:49 +00:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_MODULES ) ) ;
2013-07-01 19:45:50 +00:00
section_headers . resize ( header . e_shnum ) ;
if ( section_headers . size ( ) ! = header . e_shnum )
2010-07-13 23:07:23 +00:00
return 0 ;
2010-06-08 16:52:24 +00:00
2013-07-01 19:45:50 +00:00
const size_t sh_size = header . e_shnum * header . e_shentsize ;
const elf_off sh_offset = header . e_shoff ;
DataExtractor sh_data ;
if ( sh_data . SetData ( object_data , sh_offset , sh_size ) ! = sh_size )
2010-07-13 23:07:23 +00:00
return 0 ;
2010-06-08 16:52:24 +00:00
2010-07-13 23:07:23 +00:00
uint32_t idx ;
2013-01-25 18:06:21 +00:00
lldb : : offset_t offset ;
2013-07-01 19:45:50 +00:00
for ( idx = 0 , offset = 0 ; idx < header . e_shnum ; + + idx )
2010-07-13 23:07:23 +00:00
{
2013-07-01 19:45:50 +00:00
if ( section_headers [ idx ] . Parse ( sh_data , & offset ) = = false )
2010-07-13 23:07:23 +00:00
break ;
2010-06-08 16:52:24 +00:00
}
2013-07-01 19:45:50 +00:00
if ( idx < section_headers . size ( ) )
section_headers . resize ( idx ) ;
2010-06-08 16:52:24 +00:00
2013-07-01 19:45:50 +00:00
const unsigned strtab_idx = header . e_shstrndx ;
if ( strtab_idx & & strtab_idx < section_headers . size ( ) )
2010-06-08 16:52:24 +00:00
{
2013-07-01 19:45:50 +00:00
const ELFSectionHeaderInfo & sheader = section_headers [ strtab_idx ] ;
const size_t byte_size = sheader . sh_size ;
const Elf64_Off offset = sheader . sh_offset ;
lldb_private : : DataExtractor shstr_data ;
2010-07-13 23:07:23 +00:00
2013-07-01 19:45:50 +00:00
if ( shstr_data . SetData ( object_data , offset , byte_size ) = = byte_size )
2010-06-08 16:52:24 +00:00
{
2013-07-01 19:45:50 +00:00
for ( SectionHeaderCollIter I = section_headers . begin ( ) ;
I ! = section_headers . end ( ) ; + + I )
{
static ConstString g_sect_name_gnu_debuglink ( " .gnu_debuglink " ) ;
const ELFSectionHeaderInfo & header = * I ;
const uint64_t section_size = header . sh_type = = SHT_NOBITS ? 0 : header . sh_size ;
ConstString name ( shstr_data . PeekCStr ( I - > sh_name ) ) ;
I - > section_name = name ;
2010-06-08 16:52:24 +00:00
2013-07-01 19:45:50 +00:00
if ( name = = g_sect_name_gnu_debuglink )
{
DataExtractor data ;
if ( section_size & & ( data . SetData ( object_data , header . sh_offset , section_size ) = = section_size ) )
{
lldb : : offset_t gnu_debuglink_offset = 0 ;
gnu_debuglink_file = data . GetCStr ( & gnu_debuglink_offset ) ;
gnu_debuglink_offset = llvm : : RoundUpToAlignment ( gnu_debuglink_offset , 4 ) ;
data . GetU32 ( & gnu_debuglink_offset , & gnu_debuglink_crc , 1 ) ;
}
}
2014-06-27 16:52:49 +00:00
// Process ELF note section entries.
2015-03-18 10:36:27 +00:00
bool is_note_header = ( header . sh_type = = SHT_NOTE ) ;
// The section header ".note.android.ident" is stored as a
// PROGBITS type header but it is actually a note header.
static ConstString g_sect_name_android_ident ( " .note.android.ident " ) ;
if ( ! is_note_header & & name = = g_sect_name_android_ident )
is_note_header = true ;
if ( is_note_header )
2013-07-01 19:45:50 +00:00
{
2014-06-27 16:52:49 +00:00
// Allow notes to refine module info.
2013-07-01 19:45:50 +00:00
DataExtractor data ;
if ( section_size & & ( data . SetData ( object_data , header . sh_offset , section_size ) = = section_size ) )
{
2014-06-27 16:52:49 +00:00
Error error = RefineModuleDetailsFromNote ( data , arch_spec , uuid ) ;
if ( error . Fail ( ) )
{
if ( log )
log - > Printf ( " ObjectFileELF::%s ELF note processing failed: %s " , __FUNCTION__ , error . AsCString ( ) ) ;
}
2013-07-01 19:45:50 +00:00
}
}
}
return section_headers . size ( ) ;
2010-06-08 16:52:24 +00:00
}
}
2013-07-01 19:45:50 +00:00
section_headers . clear ( ) ;
return 0 ;
}
2013-07-11 20:39:00 +00:00
size_t
ObjectFileELF : : GetProgramHeaderCount ( )
{
return ParseProgramHeaders ( ) ;
}
const elf : : ELFProgramHeader *
ObjectFileELF : : GetProgramHeaderByIndex ( lldb : : user_id_t id )
{
if ( ! id | | ! ParseProgramHeaders ( ) )
return NULL ;
if ( - - id < m_program_headers . size ( ) )
return & m_program_headers [ id ] ;
return NULL ;
}
DataExtractor
ObjectFileELF : : GetSegmentDataByIndex ( lldb : : user_id_t id )
{
const elf : : ELFProgramHeader * segment_header = GetProgramHeaderByIndex ( id ) ;
if ( segment_header = = NULL )
return DataExtractor ( ) ;
return DataExtractor ( m_data , segment_header - > p_offset , segment_header - > p_filesz ) ;
}
2015-03-04 10:25:22 +00:00
std : : string
ObjectFileELF : : StripLinkerSymbolAnnotations ( llvm : : StringRef symbol_name ) const
{
size_t pos = symbol_name . find ( " @ " ) ;
return symbol_name . substr ( 0 , pos ) . str ( ) ;
}
2013-07-01 19:45:50 +00:00
//----------------------------------------------------------------------
// ParseSectionHeaders
//----------------------------------------------------------------------
size_t
ObjectFileELF : : ParseSectionHeaders ( )
{
2014-06-27 16:52:49 +00:00
return GetSectionHeaderInfo ( m_section_headers , m_data , m_header , m_uuid , m_gnu_debuglink_file , m_gnu_debuglink_crc , m_arch_spec ) ;
2010-06-08 16:52:24 +00:00
}
2013-07-01 19:45:50 +00:00
const ObjectFileELF : : ELFSectionHeaderInfo *
2011-03-30 16:07:05 +00:00
ObjectFileELF : : GetSectionHeaderByIndex ( lldb : : user_id_t id )
{
2013-07-11 20:39:00 +00:00
if ( ! id | | ! ParseSectionHeaders ( ) )
2011-03-30 16:07:05 +00:00
return NULL ;
if ( - - id < m_section_headers . size ( ) )
return & m_section_headers [ id ] ;
return NULL ;
}
2013-07-10 01:23:25 +00:00
void
ObjectFileELF : : CreateSections ( SectionList & unified_section_list )
2010-06-08 16:52:24 +00:00
{
2013-07-10 01:23:25 +00:00
if ( ! m_sections_ap . get ( ) & & ParseSectionHeaders ( ) )
2010-06-08 16:52:24 +00:00
{
m_sections_ap . reset ( new SectionList ( ) ) ;
2010-07-13 23:07:23 +00:00
for ( SectionHeaderCollIter I = m_section_headers . begin ( ) ;
I ! = m_section_headers . end ( ) ; + + I )
{
2013-07-01 19:45:50 +00:00
const ELFSectionHeaderInfo & header = * I ;
2010-07-13 23:07:23 +00:00
2013-07-01 19:45:50 +00:00
ConstString & name = I - > section_name ;
2012-03-27 02:40:46 +00:00
const uint64_t file_size = header . sh_type = = SHT_NOBITS ? 0 : header . sh_size ;
const uint64_t vm_size = header . sh_flags & SHF_ALLOC ? header . sh_size : 0 ;
2010-07-13 23:07:23 +00:00
2010-07-21 22:54:26 +00:00
static ConstString g_sect_name_text ( " .text " ) ;
static ConstString g_sect_name_data ( " .data " ) ;
static ConstString g_sect_name_bss ( " .bss " ) ;
2012-03-27 21:10:07 +00:00
static ConstString g_sect_name_tdata ( " .tdata " ) ;
static ConstString g_sect_name_tbss ( " .tbss " ) ;
2010-07-21 22:54:26 +00:00
static ConstString g_sect_name_dwarf_debug_abbrev ( " .debug_abbrev " ) ;
static ConstString g_sect_name_dwarf_debug_aranges ( " .debug_aranges " ) ;
static ConstString g_sect_name_dwarf_debug_frame ( " .debug_frame " ) ;
static ConstString g_sect_name_dwarf_debug_info ( " .debug_info " ) ;
static ConstString g_sect_name_dwarf_debug_line ( " .debug_line " ) ;
static ConstString g_sect_name_dwarf_debug_loc ( " .debug_loc " ) ;
static ConstString g_sect_name_dwarf_debug_macinfo ( " .debug_macinfo " ) ;
static ConstString g_sect_name_dwarf_debug_pubnames ( " .debug_pubnames " ) ;
static ConstString g_sect_name_dwarf_debug_pubtypes ( " .debug_pubtypes " ) ;
static ConstString g_sect_name_dwarf_debug_ranges ( " .debug_ranges " ) ;
static ConstString g_sect_name_dwarf_debug_str ( " .debug_str " ) ;
static ConstString g_sect_name_eh_frame ( " .eh_frame " ) ;
SectionType sect_type = eSectionTypeOther ;
2012-03-27 21:10:07 +00:00
bool is_thread_specific = false ;
2013-07-01 19:45:50 +00:00
2010-07-21 22:54:26 +00:00
if ( name = = g_sect_name_text ) sect_type = eSectionTypeCode ;
else if ( name = = g_sect_name_data ) sect_type = eSectionTypeData ;
else if ( name = = g_sect_name_bss ) sect_type = eSectionTypeZeroFill ;
2012-03-27 21:10:07 +00:00
else if ( name = = g_sect_name_tdata )
{
sect_type = eSectionTypeData ;
is_thread_specific = true ;
}
else if ( name = = g_sect_name_tbss )
{
sect_type = eSectionTypeZeroFill ;
is_thread_specific = true ;
}
2013-07-01 19:45:50 +00:00
// .debug_abbrev – Abbreviations used in the .debug_info section
// .debug_aranges – Lookup table for mapping addresses to compilation units
// .debug_frame – Call frame information
// .debug_info – The core DWARF information section
// .debug_line – Line number information
// .debug_loc – Location lists used in DW_AT_location attributes
// .debug_macinfo – Macro information
// .debug_pubnames – Lookup table for mapping object and function names to compilation units
// .debug_pubtypes – Lookup table for mapping type names to compilation units
// .debug_ranges – Address ranges used in DW_AT_ranges attributes
// .debug_str – String table used in .debug_info
2013-07-17 00:26:30 +00:00
// MISSING? .gnu_debugdata - "mini debuginfo / MiniDebugInfo" section, http://sourceware.org/gdb/onlinedocs/gdb/MiniDebugInfo.html
// MISSING? .debug-index - http://src.chromium.org/viewvc/chrome/trunk/src/build/gdb-add-index?pathrev=144644
2013-07-01 19:45:50 +00:00
// MISSING? .debug_types - Type descriptions from DWARF 4? See http://gcc.gnu.org/wiki/DwarfSeparateTypeInfo
2010-07-21 22:54:26 +00:00
else if ( name = = g_sect_name_dwarf_debug_abbrev ) sect_type = eSectionTypeDWARFDebugAbbrev ;
else if ( name = = g_sect_name_dwarf_debug_aranges ) sect_type = eSectionTypeDWARFDebugAranges ;
else if ( name = = g_sect_name_dwarf_debug_frame ) sect_type = eSectionTypeDWARFDebugFrame ;
else if ( name = = g_sect_name_dwarf_debug_info ) sect_type = eSectionTypeDWARFDebugInfo ;
else if ( name = = g_sect_name_dwarf_debug_line ) sect_type = eSectionTypeDWARFDebugLine ;
else if ( name = = g_sect_name_dwarf_debug_loc ) sect_type = eSectionTypeDWARFDebugLoc ;
else if ( name = = g_sect_name_dwarf_debug_macinfo ) sect_type = eSectionTypeDWARFDebugMacInfo ;
else if ( name = = g_sect_name_dwarf_debug_pubnames ) sect_type = eSectionTypeDWARFDebugPubNames ;
else if ( name = = g_sect_name_dwarf_debug_pubtypes ) sect_type = eSectionTypeDWARFDebugPubTypes ;
else if ( name = = g_sect_name_dwarf_debug_ranges ) sect_type = eSectionTypeDWARFDebugRanges ;
else if ( name = = g_sect_name_dwarf_debug_str ) sect_type = eSectionTypeDWARFDebugStr ;
else if ( name = = g_sect_name_eh_frame ) sect_type = eSectionTypeEHFrame ;
2013-07-01 19:45:50 +00:00
switch ( header . sh_type )
2013-05-23 20:57:03 +00:00
{
2013-07-01 19:45:50 +00:00
case SHT_SYMTAB :
assert ( sect_type = = eSectionTypeOther ) ;
sect_type = eSectionTypeELFSymbolTable ;
break ;
case SHT_DYNSYM :
assert ( sect_type = = eSectionTypeOther ) ;
sect_type = eSectionTypeELFDynamicSymbols ;
break ;
case SHT_RELA :
case SHT_REL :
assert ( sect_type = = eSectionTypeOther ) ;
sect_type = eSectionTypeELFRelocationEntries ;
break ;
case SHT_DYNAMIC :
assert ( sect_type = = eSectionTypeOther ) ;
sect_type = eSectionTypeELFDynamicLinkInfo ;
break ;
2013-05-23 20:57:03 +00:00
}
2013-07-01 19:45:50 +00:00
2014-09-29 08:02:24 +00:00
if ( eSectionTypeOther = = sect_type )
{
// the kalimba toolchain assumes that ELF section names are free-form. It does
// supports linkscripts which (can) give rise to various arbitarily named
// sections being "Code" or "Data".
sect_type = kalimbaSectionType ( m_header , header ) ;
}
const uint32_t target_bytes_size =
2014-10-15 08:21:54 +00:00
( eSectionTypeData = = sect_type | | eSectionTypeZeroFill = = sect_type ) ?
2014-09-29 08:02:24 +00:00
m_arch_spec . GetDataByteSize ( ) :
eSectionTypeCode = = sect_type ?
m_arch_spec . GetCodeByteSize ( ) : 1 ;
2014-06-25 05:42:32 +00:00
elf : : elf_xword log2align = ( header . sh_addralign = = 0 )
? 0
: llvm : : Log2_64 ( header . sh_addralign ) ;
2013-07-10 01:23:25 +00:00
SectionSP section_sp ( new Section ( GetModule ( ) , // Module to which this section belongs.
this , // ObjectFile to which this section belongs and should read section data from.
SectionIndex ( I ) , // Section ID.
name , // Section name.
sect_type , // Section type.
header . sh_addr , // VM address.
vm_size , // VM size in bytes of this section.
header . sh_offset , // Offset of this section in the file.
file_size , // Size of the section as found in the file.
2014-06-25 05:42:32 +00:00
log2align , // Alignment of the section
2014-09-29 08:02:24 +00:00
header . sh_flags , // Flags for this section.
target_bytes_size ) ) ; // Number of host bytes per target byte
2010-07-13 23:07:23 +00:00
2012-03-27 21:10:07 +00:00
if ( is_thread_specific )
section_sp - > SetIsThreadSpecific ( is_thread_specific ) ;
m_sections_ap - > AddSection ( section_sp ) ;
2010-06-08 16:52:24 +00:00
}
}
2010-07-13 23:07:23 +00:00
2013-07-10 01:23:25 +00:00
if ( m_sections_ap . get ( ) )
{
if ( GetType ( ) = = eTypeDebugInfo )
{
static const SectionType g_sections [ ] =
{
eSectionTypeDWARFDebugAranges ,
eSectionTypeDWARFDebugInfo ,
eSectionTypeDWARFDebugAbbrev ,
eSectionTypeDWARFDebugFrame ,
eSectionTypeDWARFDebugLine ,
eSectionTypeDWARFDebugStr ,
eSectionTypeDWARFDebugLoc ,
eSectionTypeDWARFDebugMacInfo ,
eSectionTypeDWARFDebugPubNames ,
eSectionTypeDWARFDebugPubTypes ,
eSectionTypeDWARFDebugRanges ,
eSectionTypeELFSymbolTable ,
} ;
SectionList * elf_section_list = m_sections_ap . get ( ) ;
for ( size_t idx = 0 ; idx < sizeof ( g_sections ) / sizeof ( g_sections [ 0 ] ) ; + + idx )
{
SectionType section_type = g_sections [ idx ] ;
SectionSP section_sp ( elf_section_list - > FindSectionByType ( section_type , true ) ) ;
if ( section_sp )
{
SectionSP module_section_sp ( unified_section_list . FindSectionByType ( section_type , true ) ) ;
if ( module_section_sp )
unified_section_list . ReplaceSection ( module_section_sp - > GetID ( ) , section_sp ) ;
else
unified_section_list . AddSection ( section_sp ) ;
}
}
}
else
{
unified_section_list = * m_sections_ap ;
}
}
2010-06-08 16:52:24 +00:00
}
2013-07-10 01:23:25 +00:00
// private
2013-07-01 19:45:50 +00:00
unsigned
2013-07-10 01:23:25 +00:00
ObjectFileELF : : ParseSymbols ( Symtab * symtab ,
user_id_t start_id ,
SectionList * section_list ,
const size_t num_symbols ,
const DataExtractor & symtab_data ,
const DataExtractor & strtab_data )
2010-06-08 16:52:24 +00:00
{
2010-07-13 23:07:23 +00:00
ELFSymbol symbol ;
2013-01-25 18:06:21 +00:00
lldb : : offset_t offset = 0 ;
2010-07-13 23:07:23 +00:00
2010-06-08 16:52:24 +00:00
static ConstString text_section_name ( " .text " ) ;
static ConstString init_section_name ( " .init " ) ;
static ConstString fini_section_name ( " .fini " ) ;
static ConstString ctors_section_name ( " .ctors " ) ;
static ConstString dtors_section_name ( " .dtors " ) ;
static ConstString data_section_name ( " .data " ) ;
static ConstString rodata_section_name ( " .rodata " ) ;
static ConstString rodata1_section_name ( " .rodata1 " ) ;
static ConstString data2_section_name ( " .data1 " ) ;
static ConstString bss_section_name ( " .bss " ) ;
2014-10-31 02:34:28 +00:00
static ConstString opd_section_name ( " .opd " ) ; // For ppc64
2010-06-08 16:52:24 +00:00
2013-04-13 23:17:23 +00:00
//StreamFile strm(stdout, false);
2011-03-30 16:07:05 +00:00
unsigned i ;
for ( i = 0 ; i < num_symbols ; + + i )
2010-06-08 16:52:24 +00:00
{
2010-07-13 23:07:23 +00:00
if ( symbol . Parse ( symtab_data , & offset ) = = false )
2010-06-08 16:52:24 +00:00
break ;
2013-04-13 23:17:23 +00:00
const char * symbol_name = strtab_data . PeekCStr ( symbol . st_name ) ;
2014-03-05 10:12:43 +00:00
// No need to add non-section symbols that have no names
if ( symbol . getType ( ) ! = STT_SECTION & &
( symbol_name = = NULL | | symbol_name [ 0 ] = = ' \0 ' ) )
2013-04-13 23:17:23 +00:00
continue ;
//symbol.Dump (&strm, i, &strtab_data, section_list);
2010-06-08 16:52:24 +00:00
2012-02-24 01:59:29 +00:00
SectionSP symbol_section_sp ;
2010-06-08 16:52:24 +00:00
SymbolType symbol_type = eSymbolTypeInvalid ;
2010-07-13 23:07:23 +00:00
Elf64_Half symbol_idx = symbol . st_shndx ;
2010-06-08 16:52:24 +00:00
2010-07-13 23:07:23 +00:00
switch ( symbol_idx )
2010-06-08 16:52:24 +00:00
{
case SHN_ABS :
symbol_type = eSymbolTypeAbsolute ;
break ;
case SHN_UNDEF :
symbol_type = eSymbolTypeUndefined ;
break ;
default :
2012-02-24 01:59:29 +00:00
symbol_section_sp = section_list - > GetSectionAtIndex ( symbol_idx ) ;
2010-06-08 16:52:24 +00:00
break ;
}
2013-02-12 18:30:30 +00:00
// If a symbol is undefined do not process it further even if it has a STT type
if ( symbol_type ! = eSymbolTypeUndefined )
2010-06-08 16:52:24 +00:00
{
2013-02-12 18:30:30 +00:00
switch ( symbol . getType ( ) )
{
default :
case STT_NOTYPE :
// The symbol's type is not specified.
break ;
2010-06-08 16:52:24 +00:00
2013-02-12 18:30:30 +00:00
case STT_OBJECT :
// The symbol is associated with a data object, such as a variable,
// an array, etc.
symbol_type = eSymbolTypeData ;
break ;
2010-06-08 16:52:24 +00:00
2013-02-12 18:30:30 +00:00
case STT_FUNC :
// The symbol is associated with a function or other executable code.
symbol_type = eSymbolTypeCode ;
break ;
2010-06-08 16:52:24 +00:00
2013-02-12 18:30:30 +00:00
case STT_SECTION :
// The symbol is associated with a section. Symbol table entries of
// this type exist primarily for relocation and normally have
// STB_LOCAL binding.
break ;
2010-06-08 16:52:24 +00:00
2013-02-12 18:30:30 +00:00
case STT_FILE :
// Conventionally, the symbol's name gives the name of the source
// file associated with the object file. A file symbol has STB_LOCAL
// binding, its section index is SHN_ABS, and it precedes the other
// STB_LOCAL symbols for the file, if it is present.
2013-04-13 23:17:23 +00:00
symbol_type = eSymbolTypeSourceFile ;
2013-02-12 18:30:30 +00:00
break ;
2013-02-27 20:13:38 +00:00
case STT_GNU_IFUNC :
// The symbol is associated with an indirect function. The actual
// function will be resolved if it is referenced.
symbol_type = eSymbolTypeResolver ;
break ;
2013-02-12 18:30:30 +00:00
}
2010-06-08 16:52:24 +00:00
}
if ( symbol_type = = eSymbolTypeInvalid )
{
2012-02-24 01:59:29 +00:00
if ( symbol_section_sp )
2010-06-08 16:52:24 +00:00
{
2012-02-24 01:59:29 +00:00
const ConstString & sect_name = symbol_section_sp - > GetName ( ) ;
2010-06-08 16:52:24 +00:00
if ( sect_name = = text_section_name | |
sect_name = = init_section_name | |
sect_name = = fini_section_name | |
sect_name = = ctors_section_name | |
sect_name = = dtors_section_name )
{
symbol_type = eSymbolTypeCode ;
}
2010-07-13 23:07:23 +00:00
else if ( sect_name = = data_section_name | |
sect_name = = data2_section_name | |
sect_name = = rodata_section_name | |
sect_name = = rodata1_section_name | |
sect_name = = bss_section_name )
2010-06-08 16:52:24 +00:00
{
symbol_type = eSymbolTypeData ;
}
}
}
2014-09-15 16:27:44 +00:00
ArchSpec arch ;
2014-09-15 22:33:39 +00:00
int64_t symbol_value_offset = 0 ;
uint32_t additional_flags = 0 ;
2014-09-15 16:27:44 +00:00
if ( GetArchitecture ( arch ) & &
arch . GetMachine ( ) = = llvm : : Triple : : arm )
{
// ELF symbol tables may contain some mapping symbols. They provide
// information about the underlying data. There are three of them
// currently defined:
// $a[.<any>]* - marks an ARM instruction sequence
// $t[.<any>]* - marks a THUMB instruction sequence
// $d[.<any>]* - marks a data item sequence (e.g. lit pool)
// These symbols interfere with normal debugger operations and we
// don't need them. We can drop them here.
static const llvm : : StringRef g_armelf_arm_marker ( " $a " ) ;
static const llvm : : StringRef g_armelf_thumb_marker ( " $t " ) ;
static const llvm : : StringRef g_armelf_data_marker ( " $d " ) ;
llvm : : StringRef symbol_name_ref ( symbol_name ) ;
if ( symbol_name & &
( symbol_name_ref . startswith ( g_armelf_arm_marker ) | |
symbol_name_ref . startswith ( g_armelf_thumb_marker ) | |
symbol_name_ref . startswith ( g_armelf_data_marker ) ) )
continue ;
2014-09-15 22:33:39 +00:00
// THUMB functions have the lower bit of their address set. Fixup
// the actual address and mark the symbol as THUMB.
if ( symbol_type = = eSymbolTypeCode & & symbol . st_value & 1 )
{
// Substracting 1 from the address effectively unsets
// the low order bit, which results in the address
// actually pointing to the beginning of the symbol.
// This delta will be used below in conjuction with
// symbol.st_value to produce the final symbol_value
// that we store in the symtab.
symbol_value_offset = - 1 ;
additional_flags = ARM_ELF_SYM_IS_THUMB ;
}
2014-09-15 16:27:44 +00:00
}
2013-07-10 01:23:25 +00:00
// If the symbol section we've found has no data (SHT_NOBITS), then check the module section
// list. This can happen if we're parsing the debug file and it has no .text section, for example.
2013-07-01 19:45:50 +00:00
if ( symbol_section_sp & & ( symbol_section_sp - > GetFileSize ( ) = = 0 ) )
{
ModuleSP module_sp ( GetModule ( ) ) ;
if ( module_sp )
{
2013-07-10 01:23:25 +00:00
SectionList * module_section_list = module_sp - > GetSectionList ( ) ;
if ( module_section_list & & module_section_list ! = section_list )
2013-07-01 19:45:50 +00:00
{
const ConstString & sect_name = symbol_section_sp - > GetName ( ) ;
2013-07-10 01:23:25 +00:00
lldb : : SectionSP section_sp ( module_section_list - > FindSectionByName ( sect_name ) ) ;
2013-07-01 19:45:50 +00:00
if ( section_sp & & section_sp - > GetFileSize ( ) )
{
symbol_section_sp = section_sp ;
}
}
}
}
2014-09-15 22:33:39 +00:00
// symbol_value_offset may contain 0 for ARM symbols or -1 for
// THUMB symbols. See above for more details.
uint64_t symbol_value = symbol . st_value | symbol_value_offset ;
2014-03-05 10:12:43 +00:00
if ( symbol_section_sp & & CalculateType ( ) ! = ObjectFile : : Type : : eTypeObjectFile )
2012-02-24 01:59:29 +00:00
symbol_value - = symbol_section_sp - > GetFileAddress ( ) ;
2010-07-13 23:07:23 +00:00
bool is_global = symbol . getBinding ( ) = = STB_GLOBAL ;
2014-09-15 22:33:39 +00:00
uint32_t flags = symbol . st_other < < 8 | symbol . st_info | additional_flags ;
2012-03-27 02:40:46 +00:00
bool is_mangled = symbol_name ? ( symbol_name [ 0 ] = = ' _ ' & & symbol_name [ 1 ] = = ' Z ' ) : false ;
2014-09-15 22:33:39 +00:00
2015-03-04 10:25:22 +00:00
llvm : : StringRef symbol_ref ( symbol_name ) ;
// Symbol names may contain @VERSION suffixes. Find those and strip them temporarily.
size_t version_pos = symbol_ref . find ( ' @ ' ) ;
bool has_suffix = version_pos ! = llvm : : StringRef : : npos ;
llvm : : StringRef symbol_bare = symbol_ref . substr ( 0 , version_pos ) ;
Mangled mangled ( ConstString ( symbol_bare ) , is_mangled ) ;
// Now append the suffix back to mangled and unmangled names. Only do it if the
// demangling was sucessful (string is not empty).
if ( has_suffix )
{
llvm : : StringRef suffix = symbol_ref . substr ( version_pos ) ;
llvm : : StringRef mangled_name = mangled . GetMangledName ( ) . GetStringRef ( ) ;
if ( ! mangled_name . empty ( ) )
mangled . SetMangledName ( ConstString ( ( mangled_name + suffix ) . str ( ) ) ) ;
llvm : : StringRef demangled_name = mangled . GetDemangledName ( ) . GetStringRef ( ) ;
if ( ! demangled_name . empty ( ) )
mangled . SetDemangledName ( ConstString ( ( demangled_name + suffix ) . str ( ) ) ) ;
}
2010-07-13 23:07:23 +00:00
Symbol dc_symbol (
2012-02-24 01:59:29 +00:00
i + start_id , // ID is the original symbol table index.
2015-03-04 10:25:22 +00:00
mangled ,
2012-02-24 01:59:29 +00:00
symbol_type , // Type of this symbol
is_global , // Is this globally visible?
false , // Is this symbol debug info?
false , // Is this symbol a trampoline?
false , // Is this symbol artificial?
2015-03-04 10:25:22 +00:00
AddressRange (
symbol_section_sp , // Section in which this symbol is defined or null.
symbol_value , // Offset in section or symbol value.
symbol . st_size ) , // Size in bytes of this symbol.
2013-04-13 23:17:23 +00:00
true , // Size is valid
2015-03-04 10:25:22 +00:00
has_suffix , // Contains linker annotations?
2012-02-24 01:59:29 +00:00
flags ) ; // Symbol flags.
2010-06-08 16:52:24 +00:00
symtab - > AddSymbol ( dc_symbol ) ;
}
2011-03-30 16:07:05 +00:00
return i ;
2010-06-08 16:52:24 +00:00
}
2011-03-30 16:07:05 +00:00
unsigned
2013-07-10 01:23:25 +00:00
ObjectFileELF : : ParseSymbolTable ( Symtab * symbol_table , user_id_t start_id , lldb_private : : Section * symtab )
2010-07-13 23:07:23 +00:00
{
2013-07-10 01:23:25 +00:00
if ( symtab - > GetObjectFile ( ) ! = this )
{
// If the symbol table section is owned by a different object file, have it do the
// parsing.
ObjectFileELF * obj_file_elf = static_cast < ObjectFileELF * > ( symtab - > GetObjectFile ( ) ) ;
return obj_file_elf - > ParseSymbolTable ( symbol_table , start_id , symtab ) ;
}
// Get section list for this object file.
SectionList * section_list = m_sections_ap . get ( ) ;
2010-07-13 23:07:23 +00:00
if ( ! section_list )
2011-03-30 16:07:05 +00:00
return 0 ;
2010-07-13 23:07:23 +00:00
2013-07-10 01:23:25 +00:00
user_id_t symtab_id = symtab - > GetID ( ) ;
const ELFSectionHeaderInfo * symtab_hdr = GetSectionHeaderByIndex ( symtab_id ) ;
2013-07-01 19:45:50 +00:00
assert ( symtab_hdr - > sh_type = = SHT_SYMTAB | |
symtab_hdr - > sh_type = = SHT_DYNSYM ) ;
2013-07-10 01:23:25 +00:00
// sh_link: section header index of associated string table.
2010-07-13 23:07:23 +00:00
// Section ID's are ones based.
2011-03-30 16:07:05 +00:00
user_id_t strtab_id = symtab_hdr - > sh_link + 1 ;
2010-07-13 23:07:23 +00:00
Section * strtab = section_list - > FindSectionByID ( strtab_id ) . get ( ) ;
2013-07-10 01:23:25 +00:00
2010-07-13 23:07:23 +00:00
if ( symtab & & strtab )
{
2013-07-10 01:23:25 +00:00
assert ( symtab - > GetObjectFile ( ) = = this ) ;
assert ( strtab - > GetObjectFile ( ) = = this ) ;
2010-07-13 23:07:23 +00:00
DataExtractor symtab_data ;
DataExtractor strtab_data ;
2012-02-05 02:38:54 +00:00
if ( ReadSectionData ( symtab , symtab_data ) & &
ReadSectionData ( strtab , strtab_data ) )
2010-07-13 23:07:23 +00:00
{
2013-07-10 01:23:25 +00:00
size_t num_symbols = symtab_data . GetByteSize ( ) / symtab_hdr - > sh_entsize ;
2014-03-22 20:23:26 +00:00
return ParseSymbols ( symbol_table , start_id , section_list ,
num_symbols , symtab_data , strtab_data ) ;
2011-03-30 16:07:05 +00:00
}
}
2014-03-22 20:23:26 +00:00
return 0 ;
2011-03-30 16:07:05 +00:00
}
size_t
ObjectFileELF : : ParseDynamicSymbols ( )
{
if ( m_dynamic_symbols . size ( ) )
return m_dynamic_symbols . size ( ) ;
SectionList * section_list = GetSectionList ( ) ;
if ( ! section_list )
2012-04-03 07:50:11 +00:00
return 0 ;
2011-03-30 16:07:05 +00:00
2013-07-10 01:23:25 +00:00
// Find the SHT_DYNAMIC section.
Section * dynsym = section_list - > FindSectionByType ( eSectionTypeELFDynamicLinkInfo , true ) . get ( ) ;
2011-03-30 16:07:05 +00:00
if ( ! dynsym )
2012-04-03 07:50:11 +00:00
return 0 ;
2013-07-10 01:23:25 +00:00
assert ( dynsym - > GetObjectFile ( ) = = this ) ;
2011-03-30 16:07:05 +00:00
ELFDynamic symbol ;
DataExtractor dynsym_data ;
2012-02-05 02:38:54 +00:00
if ( ReadSectionData ( dynsym , dynsym_data ) )
2011-03-30 16:07:05 +00:00
{
2013-01-25 18:06:21 +00:00
const lldb : : offset_t section_size = dynsym_data . GetByteSize ( ) ;
lldb : : offset_t cursor = 0 ;
2011-03-30 16:07:05 +00:00
while ( cursor < section_size )
{
if ( ! symbol . Parse ( dynsym_data , & cursor ) )
break ;
m_dynamic_symbols . push_back ( symbol ) ;
2010-07-13 23:07:23 +00:00
}
}
2011-03-30 16:07:05 +00:00
return m_dynamic_symbols . size ( ) ;
}
const ELFDynamic *
ObjectFileELF : : FindDynamicSymbol ( unsigned tag )
{
if ( ! ParseDynamicSymbols ( ) )
return NULL ;
DynamicSymbolCollIter I = m_dynamic_symbols . begin ( ) ;
DynamicSymbolCollIter E = m_dynamic_symbols . end ( ) ;
for ( ; I ! = E ; + + I )
{
ELFDynamic * symbol = & * I ;
if ( symbol - > d_tag = = tag )
return symbol ;
}
return NULL ;
}
unsigned
ObjectFileELF : : PLTRelocationType ( )
{
2013-08-22 21:25:53 +00:00
// DT_PLTREL
// This member specifies the type of relocation entry to which the
// procedure linkage table refers. The d_val member holds DT_REL or
// DT_RELA, as appropriate. All relocations in a procedure linkage table
// must use the same relocation.
2011-03-30 16:07:05 +00:00
const ELFDynamic * symbol = FindDynamicSymbol ( DT_PLTREL ) ;
if ( symbol )
return symbol - > d_val ;
return 0 ;
}
static unsigned
ParsePLTRelocations ( Symtab * symbol_table ,
user_id_t start_id ,
unsigned rel_type ,
const ELFHeader * hdr ,
const ELFSectionHeader * rel_hdr ,
const ELFSectionHeader * plt_hdr ,
const ELFSectionHeader * sym_hdr ,
2012-02-24 01:59:29 +00:00
const lldb : : SectionSP & plt_section_sp ,
2011-03-30 16:07:05 +00:00
DataExtractor & rel_data ,
DataExtractor & symtab_data ,
DataExtractor & strtab_data )
{
ELFRelocation rel ( rel_type ) ;
ELFSymbol symbol ;
2013-01-25 18:06:21 +00:00
lldb : : offset_t offset = 0 ;
2013-08-22 21:25:53 +00:00
// Clang 3.3 sets entsize to 4 for 32-bit binaries, but the plt entries are 16 bytes.
// So round the entsize up by the alignment if addralign is set.
const elf_xword plt_entsize = plt_hdr - > sh_addralign ?
llvm : : RoundUpToAlignment ( plt_hdr - > sh_entsize , plt_hdr - > sh_addralign ) : plt_hdr - > sh_entsize ;
2013-01-25 18:06:21 +00:00
const elf_xword num_relocations = rel_hdr - > sh_size / rel_hdr - > sh_entsize ;
2011-03-30 16:07:05 +00:00
typedef unsigned ( * reloc_info_fn ) ( const ELFRelocation & rel ) ;
reloc_info_fn reloc_type ;
reloc_info_fn reloc_symbol ;
2012-11-12 22:53:16 +00:00
if ( hdr - > Is32Bit ( ) )
2011-03-30 16:07:05 +00:00
{
reloc_type = ELFRelocation : : RelocType32 ;
reloc_symbol = ELFRelocation : : RelocSymbol32 ;
}
else
{
reloc_type = ELFRelocation : : RelocType64 ;
reloc_symbol = ELFRelocation : : RelocSymbol64 ;
}
unsigned slot_type = hdr - > GetRelocationJumpSlotType ( ) ;
unsigned i ;
for ( i = 0 ; i < num_relocations ; + + i )
{
if ( rel . Parse ( rel_data , & offset ) = = false )
break ;
if ( reloc_type ( rel ) ! = slot_type )
continue ;
2013-01-25 18:06:21 +00:00
lldb : : offset_t symbol_offset = reloc_symbol ( rel ) * sym_hdr - > sh_entsize ;
2011-03-30 16:07:05 +00:00
uint64_t plt_index = ( i + 1 ) * plt_entsize ;
if ( ! symbol . Parse ( symtab_data , & symbol_offset ) )
break ;
const char * symbol_name = strtab_data . PeekCStr ( symbol . st_name ) ;
2012-03-27 02:40:46 +00:00
bool is_mangled = symbol_name ? ( symbol_name [ 0 ] = = ' _ ' & & symbol_name [ 1 ] = = ' Z ' ) : false ;
2011-03-30 16:07:05 +00:00
Symbol jump_symbol (
i + start_id , // Symbol table index
symbol_name , // symbol name.
2012-03-27 02:40:46 +00:00
is_mangled , // is the symbol name mangled?
2011-03-30 16:07:05 +00:00
eSymbolTypeTrampoline , // Type of this symbol
false , // Is this globally visible?
false , // Is this symbol debug info?
true , // Is this symbol a trampoline?
true , // Is this symbol artificial?
2012-02-24 01:59:29 +00:00
plt_section_sp , // Section in which this symbol is defined or null.
2011-03-30 16:07:05 +00:00
plt_index , // Offset in section or symbol value.
plt_entsize , // Size in bytes of this symbol.
2013-04-13 23:17:23 +00:00
true , // Size is valid
2015-03-04 10:25:22 +00:00
false , // Contains linker annotations?
2011-03-30 16:07:05 +00:00
0 ) ; // Symbol flags.
symbol_table - > AddSymbol ( jump_symbol ) ;
}
return i ;
}
unsigned
ObjectFileELF : : ParseTrampolineSymbols ( Symtab * symbol_table ,
user_id_t start_id ,
2013-07-01 19:45:50 +00:00
const ELFSectionHeaderInfo * rel_hdr ,
2011-03-30 16:07:05 +00:00
user_id_t rel_id )
{
assert ( rel_hdr - > sh_type = = SHT_RELA | | rel_hdr - > sh_type = = SHT_REL ) ;
2013-07-10 01:23:25 +00:00
// The link field points to the associated symbol table. The info field
2011-03-30 16:07:05 +00:00
// points to the section holding the plt.
user_id_t symtab_id = rel_hdr - > sh_link ;
user_id_t plt_id = rel_hdr - > sh_info ;
if ( ! symtab_id | | ! plt_id )
return 0 ;
// Section ID's are ones based;
symtab_id + + ;
plt_id + + ;
2013-07-01 19:45:50 +00:00
const ELFSectionHeaderInfo * plt_hdr = GetSectionHeaderByIndex ( plt_id ) ;
2011-03-30 16:07:05 +00:00
if ( ! plt_hdr )
return 0 ;
2013-07-01 19:45:50 +00:00
const ELFSectionHeaderInfo * sym_hdr = GetSectionHeaderByIndex ( symtab_id ) ;
2011-03-30 16:07:05 +00:00
if ( ! sym_hdr )
return 0 ;
2013-07-10 01:23:25 +00:00
SectionList * section_list = m_sections_ap . get ( ) ;
2011-03-30 16:07:05 +00:00
if ( ! section_list )
return 0 ;
Section * rel_section = section_list - > FindSectionByID ( rel_id ) . get ( ) ;
if ( ! rel_section )
return 0 ;
2012-02-24 01:59:29 +00:00
SectionSP plt_section_sp ( section_list - > FindSectionByID ( plt_id ) ) ;
if ( ! plt_section_sp )
2011-03-30 16:07:05 +00:00
return 0 ;
Section * symtab = section_list - > FindSectionByID ( symtab_id ) . get ( ) ;
if ( ! symtab )
return 0 ;
2013-07-10 01:23:25 +00:00
// sh_link points to associated string table.
2011-03-30 16:07:05 +00:00
Section * strtab = section_list - > FindSectionByID ( sym_hdr - > sh_link + 1 ) . get ( ) ;
if ( ! strtab )
return 0 ;
DataExtractor rel_data ;
2012-02-05 02:38:54 +00:00
if ( ! ReadSectionData ( rel_section , rel_data ) )
2011-03-30 16:07:05 +00:00
return 0 ;
DataExtractor symtab_data ;
2012-02-05 02:38:54 +00:00
if ( ! ReadSectionData ( symtab , symtab_data ) )
2011-03-30 16:07:05 +00:00
return 0 ;
DataExtractor strtab_data ;
2012-02-05 02:38:54 +00:00
if ( ! ReadSectionData ( strtab , strtab_data ) )
2011-03-30 16:07:05 +00:00
return 0 ;
unsigned rel_type = PLTRelocationType ( ) ;
if ( ! rel_type )
return 0 ;
2012-02-24 01:59:29 +00:00
return ParsePLTRelocations ( symbol_table ,
start_id ,
rel_type ,
& m_header ,
rel_hdr ,
plt_hdr ,
sym_hdr ,
plt_section_sp ,
rel_data ,
symtab_data ,
strtab_data ) ;
2010-07-13 23:07:23 +00:00
}
2010-06-08 16:52:24 +00:00
2014-03-05 10:12:43 +00:00
unsigned
ObjectFileELF : : RelocateSection ( Symtab * symtab , const ELFHeader * hdr , const ELFSectionHeader * rel_hdr ,
const ELFSectionHeader * symtab_hdr , const ELFSectionHeader * debug_hdr ,
DataExtractor & rel_data , DataExtractor & symtab_data ,
DataExtractor & debug_data , Section * rel_section )
{
ELFRelocation rel ( rel_hdr - > sh_type ) ;
lldb : : addr_t offset = 0 ;
const unsigned num_relocations = rel_hdr - > sh_size / rel_hdr - > sh_entsize ;
typedef unsigned ( * reloc_info_fn ) ( const ELFRelocation & rel ) ;
reloc_info_fn reloc_type ;
reloc_info_fn reloc_symbol ;
if ( hdr - > Is32Bit ( ) )
{
reloc_type = ELFRelocation : : RelocType32 ;
reloc_symbol = ELFRelocation : : RelocSymbol32 ;
}
else
{
reloc_type = ELFRelocation : : RelocType64 ;
reloc_symbol = ELFRelocation : : RelocSymbol64 ;
}
for ( unsigned i = 0 ; i < num_relocations ; + + i )
{
if ( rel . Parse ( rel_data , & offset ) = = false )
break ;
Symbol * symbol = NULL ;
if ( hdr - > Is32Bit ( ) )
{
switch ( reloc_type ( rel ) ) {
case R_386_32 :
case R_386_PC32 :
default :
assert ( false & & " unexpected relocation type " ) ;
}
} else {
switch ( reloc_type ( rel ) ) {
case R_X86_64_64 :
{
symbol = symtab - > FindSymbolByID ( reloc_symbol ( rel ) ) ;
if ( symbol )
{
addr_t value = symbol - > GetAddress ( ) . GetFileAddress ( ) ;
DataBufferSP & data_buffer_sp = debug_data . GetSharedDataBuffer ( ) ;
uint64_t * dst = reinterpret_cast < uint64_t * > ( data_buffer_sp - > GetBytes ( ) + rel_section - > GetFileOffset ( ) + ELFRelocation : : RelocOffset64 ( rel ) ) ;
* dst = value + ELFRelocation : : RelocAddend64 ( rel ) ;
}
break ;
}
case R_X86_64_32 :
case R_X86_64_32S :
{
symbol = symtab - > FindSymbolByID ( reloc_symbol ( rel ) ) ;
if ( symbol )
{
addr_t value = symbol - > GetAddress ( ) . GetFileAddress ( ) ;
value + = ELFRelocation : : RelocAddend32 ( rel ) ;
assert ( ( reloc_type ( rel ) = = R_X86_64_32 & & ( value < = UINT32_MAX ) ) | |
( reloc_type ( rel ) = = R_X86_64_32S & &
( ( int64_t ) value < = INT32_MAX & & ( int64_t ) value > = INT32_MIN ) ) ) ;
uint32_t truncated_addr = ( value & 0xFFFFFFFF ) ;
DataBufferSP & data_buffer_sp = debug_data . GetSharedDataBuffer ( ) ;
uint32_t * dst = reinterpret_cast < uint32_t * > ( data_buffer_sp - > GetBytes ( ) + rel_section - > GetFileOffset ( ) + ELFRelocation : : RelocOffset32 ( rel ) ) ;
* dst = truncated_addr ;
}
break ;
}
case R_X86_64_PC32 :
default :
assert ( false & & " unexpected relocation type " ) ;
}
}
}
return 0 ;
}
unsigned
ObjectFileELF : : RelocateDebugSections ( const ELFSectionHeader * rel_hdr , user_id_t rel_id )
{
assert ( rel_hdr - > sh_type = = SHT_RELA | | rel_hdr - > sh_type = = SHT_REL ) ;
// Parse in the section list if needed.
SectionList * section_list = GetSectionList ( ) ;
if ( ! section_list )
return 0 ;
// Section ID's are ones based.
user_id_t symtab_id = rel_hdr - > sh_link + 1 ;
user_id_t debug_id = rel_hdr - > sh_info + 1 ;
const ELFSectionHeader * symtab_hdr = GetSectionHeaderByIndex ( symtab_id ) ;
if ( ! symtab_hdr )
return 0 ;
const ELFSectionHeader * debug_hdr = GetSectionHeaderByIndex ( debug_id ) ;
if ( ! debug_hdr )
return 0 ;
Section * rel = section_list - > FindSectionByID ( rel_id ) . get ( ) ;
if ( ! rel )
return 0 ;
Section * symtab = section_list - > FindSectionByID ( symtab_id ) . get ( ) ;
if ( ! symtab )
return 0 ;
Section * debug = section_list - > FindSectionByID ( debug_id ) . get ( ) ;
if ( ! debug )
return 0 ;
DataExtractor rel_data ;
DataExtractor symtab_data ;
DataExtractor debug_data ;
if ( ReadSectionData ( rel , rel_data ) & &
ReadSectionData ( symtab , symtab_data ) & &
ReadSectionData ( debug , debug_data ) )
{
RelocateSection ( m_symtab_ap . get ( ) , & m_header , rel_hdr , symtab_hdr , debug_hdr ,
rel_data , symtab_data , debug_data , debug ) ;
}
return 0 ;
}
2010-06-08 16:52:24 +00:00
Symtab *
2013-07-10 01:23:25 +00:00
ObjectFileELF : : GetSymtab ( )
2010-06-08 16:52:24 +00:00
{
2013-07-01 19:45:50 +00:00
ModuleSP module_sp ( GetModule ( ) ) ;
2013-07-10 01:23:25 +00:00
if ( ! module_sp )
return NULL ;
2013-07-01 19:45:50 +00:00
2013-07-10 01:23:25 +00:00
// We always want to use the main object file so we (hopefully) only have one cached copy
// of our symtab, dynamic sections, etc.
ObjectFile * module_obj_file = module_sp - > GetObjectFile ( ) ;
if ( module_obj_file & & module_obj_file ! = this )
return module_obj_file - > GetSymtab ( ) ;
if ( m_symtab_ap . get ( ) = = NULL )
{
2015-03-04 10:28:15 +00:00
SectionList * section_list = module_sp - > GetSectionList ( ) ;
2013-07-01 19:45:50 +00:00
if ( ! section_list )
return NULL ;
2013-07-10 01:23:25 +00:00
uint64_t symbol_id = 0 ;
lldb_private : : Mutex : : Locker locker ( module_sp - > GetMutex ( ) ) ;
2010-06-08 16:52:24 +00:00
2013-07-10 01:23:25 +00:00
m_symtab_ap . reset ( new Symtab ( this ) ) ;
2010-06-08 16:52:24 +00:00
2013-07-01 19:45:50 +00:00
// Sharable objects and dynamic executables usually have 2 distinct symbol
// tables, one named ".symtab", and the other ".dynsym". The dynsym is a smaller
// version of the symtab that only contains global symbols. The information found
// in the dynsym is therefore also found in the symtab, while the reverse is not
// necessarily true.
2013-07-10 01:23:25 +00:00
Section * symtab = section_list - > FindSectionByType ( eSectionTypeELFSymbolTable , true ) . get ( ) ;
if ( ! symtab )
2013-07-01 19:45:50 +00:00
{
// The symtab section is non-allocable and can be stripped, so if it doesn't exist
// then use the dynsym section which should always be there.
2013-07-10 01:23:25 +00:00
symtab = section_list - > FindSectionByType ( eSectionTypeELFDynamicSymbols , true ) . get ( ) ;
2013-07-01 19:45:50 +00:00
}
2013-07-10 01:23:25 +00:00
if ( symtab )
symbol_id + = ParseSymbolTable ( m_symtab_ap . get ( ) , symbol_id , symtab ) ;
2010-07-13 23:07:23 +00:00
2013-08-22 21:25:53 +00:00
// DT_JMPREL
// If present, this entry's d_ptr member holds the address of relocation
// entries associated solely with the procedure linkage table. Separating
// these relocation entries lets the dynamic linker ignore them during
// process initialization, if lazy binding is enabled. If this entry is
// present, the related entries of types DT_PLTRELSZ and DT_PLTREL must
// also be present.
2013-07-10 01:23:25 +00:00
const ELFDynamic * symbol = FindDynamicSymbol ( DT_JMPREL ) ;
if ( symbol )
2010-07-13 23:07:23 +00:00
{
2013-08-22 21:25:53 +00:00
// Synthesize trampoline symbols to help navigate the PLT.
2013-07-10 01:23:25 +00:00
addr_t addr = symbol - > d_ptr ;
Section * reloc_section = section_list - > FindSectionContainingFileAddress ( addr ) . get ( ) ;
if ( reloc_section )
2013-07-01 19:45:50 +00:00
{
2013-07-10 01:23:25 +00:00
user_id_t reloc_id = reloc_section - > GetID ( ) ;
const ELFSectionHeaderInfo * reloc_header = GetSectionHeaderByIndex ( reloc_id ) ;
assert ( reloc_header ) ;
2013-07-01 19:45:50 +00:00
2013-07-10 01:23:25 +00:00
ParseTrampolineSymbols ( m_symtab_ap . get ( ) , symbol_id , reloc_header , reloc_id ) ;
2013-07-01 19:45:50 +00:00
}
}
}
2014-03-05 10:12:43 +00:00
for ( SectionHeaderCollIter I = m_section_headers . begin ( ) ;
I ! = m_section_headers . end ( ) ; + + I )
{
if ( I - > sh_type = = SHT_RELA | | I - > sh_type = = SHT_REL )
{
if ( CalculateType ( ) = = eTypeObjectFile )
{
const char * section_name = I - > section_name . AsCString ( " " ) ;
if ( strstr ( section_name , " .rela.debug " ) | |
strstr ( section_name , " .rel.debug " ) )
{
const ELFSectionHeader & reloc_header = * I ;
user_id_t reloc_id = SectionIndex ( I ) ;
RelocateDebugSections ( & reloc_header , reloc_id ) ;
}
}
}
}
2013-07-10 01:23:25 +00:00
return m_symtab_ap . get ( ) ;
}
2013-09-24 15:34:13 +00:00
Symbol *
ObjectFileELF : : ResolveSymbolForAddress ( const Address & so_addr , bool verify_unique )
{
if ( ! m_symtab_ap . get ( ) )
return nullptr ; // GetSymtab() should be called first.
const SectionList * section_list = GetSectionList ( ) ;
if ( ! section_list )
return nullptr ;
if ( DWARFCallFrameInfo * eh_frame = GetUnwindTable ( ) . GetEHFrameInfo ( ) )
{
AddressRange range ;
if ( eh_frame - > GetAddressRange ( so_addr , range ) )
{
const addr_t file_addr = range . GetBaseAddress ( ) . GetFileAddress ( ) ;
Symbol * symbol = verify_unique ? m_symtab_ap - > FindSymbolContainingFileAddress ( file_addr ) : nullptr ;
if ( symbol )
return symbol ;
// Note that a (stripped) symbol won't be found by GetSymtab()...
lldb : : SectionSP eh_sym_section_sp = section_list - > FindSectionContainingFileAddress ( file_addr ) ;
if ( eh_sym_section_sp . get ( ) )
{
addr_t section_base = eh_sym_section_sp - > GetFileAddress ( ) ;
addr_t offset = file_addr - section_base ;
uint64_t symbol_id = m_symtab_ap - > GetNumSymbols ( ) ;
Symbol eh_symbol (
symbol_id , // Symbol table index.
" ??? " , // Symbol name.
false , // Is the symbol name mangled?
eSymbolTypeCode , // Type of this symbol.
true , // Is this globally visible?
false , // Is this symbol debug info?
false , // Is this symbol a trampoline?
true , // Is this symbol artificial?
eh_sym_section_sp , // Section in which this symbol is defined or null.
offset , // Offset in section or symbol value.
range . GetByteSize ( ) , // Size in bytes of this symbol.
true , // Size is valid.
2015-03-04 10:25:22 +00:00
false , // Contains linker annotations?
2013-09-24 15:34:13 +00:00
0 ) ; // Symbol flags.
if ( symbol_id = = m_symtab_ap - > AddSymbol ( eh_symbol ) )
return m_symtab_ap - > SymbolAtIndex ( symbol_id ) ;
}
}
}
return nullptr ;
}
2013-07-10 01:23:25 +00:00
bool
ObjectFileELF : : IsStripped ( )
{
// TODO: determine this for ELF
return false ;
2010-06-08 16:52:24 +00:00
}
//===----------------------------------------------------------------------===//
// Dump
//
// Dump the specifics of the runtime file container (such as any headers
// segments, sections, etc).
//----------------------------------------------------------------------
void
ObjectFileELF : : Dump ( Stream * s )
{
DumpELFHeader ( s , m_header ) ;
s - > EOL ( ) ;
DumpELFProgramHeaders ( s ) ;
s - > EOL ( ) ;
DumpELFSectionHeaders ( s ) ;
s - > EOL ( ) ;
SectionList * section_list = GetSectionList ( ) ;
if ( section_list )
2010-12-08 05:08:21 +00:00
section_list - > Dump ( s , NULL , true , UINT32_MAX ) ;
2010-06-08 16:52:24 +00:00
Symtab * symtab = GetSymtab ( ) ;
if ( symtab )
2011-03-24 21:19:54 +00:00
symtab - > Dump ( s , NULL , eSortOrderNone ) ;
2010-06-08 16:52:24 +00:00
s - > EOL ( ) ;
2010-07-13 23:07:23 +00:00
DumpDependentModules ( s ) ;
s - > EOL ( ) ;
2010-06-08 16:52:24 +00:00
}
//----------------------------------------------------------------------
// DumpELFHeader
//
// Dump the ELF header to the specified output stream
//----------------------------------------------------------------------
void
2010-07-13 23:07:23 +00:00
ObjectFileELF : : DumpELFHeader ( Stream * s , const ELFHeader & header )
{
s - > PutCString ( " ELF Header \n " ) ;
s - > Printf ( " e_ident[EI_MAG0 ] = 0x%2.2x \n " , header . e_ident [ EI_MAG0 ] ) ;
s - > Printf ( " e_ident[EI_MAG1 ] = 0x%2.2x '%c' \n " ,
header . e_ident [ EI_MAG1 ] , header . e_ident [ EI_MAG1 ] ) ;
s - > Printf ( " e_ident[EI_MAG2 ] = 0x%2.2x '%c' \n " ,
header . e_ident [ EI_MAG2 ] , header . e_ident [ EI_MAG2 ] ) ;
s - > Printf ( " e_ident[EI_MAG3 ] = 0x%2.2x '%c' \n " ,
header . e_ident [ EI_MAG3 ] , header . e_ident [ EI_MAG3 ] ) ;
s - > Printf ( " e_ident[EI_CLASS ] = 0x%2.2x \n " , header . e_ident [ EI_CLASS ] ) ;
s - > Printf ( " e_ident[EI_DATA ] = 0x%2.2x " , header . e_ident [ EI_DATA ] ) ;
2010-06-08 16:52:24 +00:00
DumpELFHeader_e_ident_EI_DATA ( s , header . e_ident [ EI_DATA ] ) ;
s - > Printf ( " \n e_ident[EI_VERSION] = 0x%2.2x \n " , header . e_ident [ EI_VERSION ] ) ;
s - > Printf ( " e_ident[EI_PAD ] = 0x%2.2x \n " , header . e_ident [ EI_PAD ] ) ;
s - > Printf ( " e_type = 0x%4.4x " , header . e_type ) ;
DumpELFHeader_e_type ( s , header . e_type ) ;
s - > Printf ( " \n e_machine = 0x%4.4x \n " , header . e_machine ) ;
s - > Printf ( " e_version = 0x%8.8x \n " , header . e_version ) ;
2012-11-29 21:49:15 +00:00
s - > Printf ( " e_entry = 0x%8.8 " PRIx64 " \n " , header . e_entry ) ;
s - > Printf ( " e_phoff = 0x%8.8 " PRIx64 " \n " , header . e_phoff ) ;
s - > Printf ( " e_shoff = 0x%8.8 " PRIx64 " \n " , header . e_shoff ) ;
2010-06-08 16:52:24 +00:00
s - > Printf ( " e_flags = 0x%8.8x \n " , header . e_flags ) ;
s - > Printf ( " e_ehsize = 0x%4.4x \n " , header . e_ehsize ) ;
s - > Printf ( " e_phentsize = 0x%4.4x \n " , header . e_phentsize ) ;
s - > Printf ( " e_phnum = 0x%4.4x \n " , header . e_phnum ) ;
s - > Printf ( " e_shentsize = 0x%4.4x \n " , header . e_shentsize ) ;
s - > Printf ( " e_shnum = 0x%4.4x \n " , header . e_shnum ) ;
s - > Printf ( " e_shstrndx = 0x%4.4x \n " , header . e_shstrndx ) ;
}
//----------------------------------------------------------------------
// DumpELFHeader_e_type
//
// Dump an token value for the ELF header member e_type
//----------------------------------------------------------------------
void
2010-07-13 23:07:23 +00:00
ObjectFileELF : : DumpELFHeader_e_type ( Stream * s , elf_half e_type )
2010-06-08 16:52:24 +00:00
{
switch ( e_type )
{
case ET_NONE : * s < < " ET_NONE " ; break ;
case ET_REL : * s < < " ET_REL " ; break ;
case ET_EXEC : * s < < " ET_EXEC " ; break ;
case ET_DYN : * s < < " ET_DYN " ; break ;
case ET_CORE : * s < < " ET_CORE " ; break ;
default :
break ;
}
}
//----------------------------------------------------------------------
// DumpELFHeader_e_ident_EI_DATA
//
// Dump an token value for the ELF header member e_ident[EI_DATA]
//----------------------------------------------------------------------
void
2010-07-13 23:07:23 +00:00
ObjectFileELF : : DumpELFHeader_e_ident_EI_DATA ( Stream * s , unsigned char ei_data )
2010-06-08 16:52:24 +00:00
{
switch ( ei_data )
{
case ELFDATANONE : * s < < " ELFDATANONE " ; break ;
case ELFDATA2LSB : * s < < " ELFDATA2LSB - Little Endian " ; break ;
case ELFDATA2MSB : * s < < " ELFDATA2MSB - Big Endian " ; break ;
default :
break ;
}
}
//----------------------------------------------------------------------
// DumpELFProgramHeader
//
// Dump a single ELF program header to the specified output stream
//----------------------------------------------------------------------
void
2010-07-13 23:07:23 +00:00
ObjectFileELF : : DumpELFProgramHeader ( Stream * s , const ELFProgramHeader & ph )
2010-06-08 16:52:24 +00:00
{
DumpELFProgramHeader_p_type ( s , ph . p_type ) ;
2012-11-29 21:49:15 +00:00
s - > Printf ( " %8.8 " PRIx64 " %8.8 " PRIx64 " %8.8 " PRIx64 , ph . p_offset , ph . p_vaddr , ph . p_paddr ) ;
s - > Printf ( " %8.8 " PRIx64 " %8.8 " PRIx64 " %8.8x ( " , ph . p_filesz , ph . p_memsz , ph . p_flags ) ;
2010-07-13 23:07:23 +00:00
2010-06-08 16:52:24 +00:00
DumpELFProgramHeader_p_flags ( s , ph . p_flags ) ;
2012-11-29 21:49:15 +00:00
s - > Printf ( " ) %8.8 " PRIx64 , ph . p_align ) ;
2010-06-08 16:52:24 +00:00
}
//----------------------------------------------------------------------
// DumpELFProgramHeader_p_type
//
// Dump an token value for the ELF program header member p_type which
// describes the type of the program header
2010-07-13 23:07:23 +00:00
// ----------------------------------------------------------------------
2010-06-08 16:52:24 +00:00
void
2010-07-13 23:07:23 +00:00
ObjectFileELF : : DumpELFProgramHeader_p_type ( Stream * s , elf_word p_type )
2010-06-08 16:52:24 +00:00
{
2013-05-23 23:01:14 +00:00
const int kStrWidth = 15 ;
2010-06-08 16:52:24 +00:00
switch ( p_type )
{
2013-05-23 23:01:14 +00:00
CASE_AND_STREAM ( s , PT_NULL , kStrWidth ) ;
CASE_AND_STREAM ( s , PT_LOAD , kStrWidth ) ;
CASE_AND_STREAM ( s , PT_DYNAMIC , kStrWidth ) ;
CASE_AND_STREAM ( s , PT_INTERP , kStrWidth ) ;
CASE_AND_STREAM ( s , PT_NOTE , kStrWidth ) ;
CASE_AND_STREAM ( s , PT_SHLIB , kStrWidth ) ;
CASE_AND_STREAM ( s , PT_PHDR , kStrWidth ) ;
CASE_AND_STREAM ( s , PT_TLS , kStrWidth ) ;
CASE_AND_STREAM ( s , PT_GNU_EH_FRAME , kStrWidth ) ;
2010-06-08 16:52:24 +00:00
default :
s - > Printf ( " 0x%8.8x%*s " , p_type , kStrWidth - 10 , " " ) ;
break ;
}
}
//----------------------------------------------------------------------
// DumpELFProgramHeader_p_flags
//
// Dump an token value for the ELF program header member p_flags
//----------------------------------------------------------------------
void
2010-07-13 23:07:23 +00:00
ObjectFileELF : : DumpELFProgramHeader_p_flags ( Stream * s , elf_word p_flags )
2010-06-08 16:52:24 +00:00
{
* s < < ( ( p_flags & PF_X ) ? " PF_X " : " " )
< < ( ( ( p_flags & PF_X ) & & ( p_flags & PF_W ) ) ? ' + ' : ' ' )
< < ( ( p_flags & PF_W ) ? " PF_W " : " " )
< < ( ( ( p_flags & PF_W ) & & ( p_flags & PF_R ) ) ? ' + ' : ' ' )
< < ( ( p_flags & PF_R ) ? " PF_R " : " " ) ;
}
//----------------------------------------------------------------------
// DumpELFProgramHeaders
//
// Dump all of the ELF program header to the specified output stream
//----------------------------------------------------------------------
void
ObjectFileELF : : DumpELFProgramHeaders ( Stream * s )
{
2015-02-23 15:33:11 +00:00
if ( ! ParseProgramHeaders ( ) )
return ;
s - > PutCString ( " Program Headers \n " ) ;
s - > PutCString ( " IDX p_type p_offset p_vaddr p_paddr "
" p_filesz p_memsz p_flags p_align \n " ) ;
s - > PutCString ( " ==== --------------- -------- -------- -------- "
" -------- -------- ------------------------- -------- \n " ) ;
uint32_t idx = 0 ;
for ( ProgramHeaderCollConstIter I = m_program_headers . begin ( ) ;
I ! = m_program_headers . end ( ) ; + + I , + + idx )
2010-06-08 16:52:24 +00:00
{
2015-02-23 15:33:11 +00:00
s - > Printf ( " [%2u] " , idx ) ;
ObjectFileELF : : DumpELFProgramHeader ( s , * I ) ;
s - > EOL ( ) ;
2010-06-08 16:52:24 +00:00
}
}
//----------------------------------------------------------------------
// DumpELFSectionHeader
//
// Dump a single ELF section header to the specified output stream
//----------------------------------------------------------------------
void
2013-07-01 19:45:50 +00:00
ObjectFileELF : : DumpELFSectionHeader ( Stream * s , const ELFSectionHeaderInfo & sh )
2010-06-08 16:52:24 +00:00
{
2010-07-13 23:07:23 +00:00
s - > Printf ( " %8.8x " , sh . sh_name ) ;
2010-06-08 16:52:24 +00:00
DumpELFSectionHeader_sh_type ( s , sh . sh_type ) ;
2012-11-29 21:49:15 +00:00
s - > Printf ( " %8.8 " PRIx64 " ( " , sh . sh_flags ) ;
2010-06-08 16:52:24 +00:00
DumpELFSectionHeader_sh_flags ( s , sh . sh_flags ) ;
2012-11-29 21:49:15 +00:00
s - > Printf ( " ) %8.8 " PRIx64 " %8.8 " PRIx64 " %8.8 " PRIx64 , sh . sh_addr , sh . sh_offset , sh . sh_size ) ;
2010-07-13 23:07:23 +00:00
s - > Printf ( " %8.8x %8.8x " , sh . sh_link , sh . sh_info ) ;
2012-11-29 21:49:15 +00:00
s - > Printf ( " %8.8 " PRIx64 " %8.8 " PRIx64 , sh . sh_addralign , sh . sh_entsize ) ;
2010-06-08 16:52:24 +00:00
}
//----------------------------------------------------------------------
// DumpELFSectionHeader_sh_type
//
// Dump an token value for the ELF section header member sh_type which
// describes the type of the section
//----------------------------------------------------------------------
void
2010-07-13 23:07:23 +00:00
ObjectFileELF : : DumpELFSectionHeader_sh_type ( Stream * s , elf_word sh_type )
2010-06-08 16:52:24 +00:00
{
const int kStrWidth = 12 ;
switch ( sh_type )
{
CASE_AND_STREAM ( s , SHT_NULL , kStrWidth ) ;
CASE_AND_STREAM ( s , SHT_PROGBITS , kStrWidth ) ;
CASE_AND_STREAM ( s , SHT_SYMTAB , kStrWidth ) ;
CASE_AND_STREAM ( s , SHT_STRTAB , kStrWidth ) ;
CASE_AND_STREAM ( s , SHT_RELA , kStrWidth ) ;
CASE_AND_STREAM ( s , SHT_HASH , kStrWidth ) ;
CASE_AND_STREAM ( s , SHT_DYNAMIC , kStrWidth ) ;
CASE_AND_STREAM ( s , SHT_NOTE , kStrWidth ) ;
CASE_AND_STREAM ( s , SHT_NOBITS , kStrWidth ) ;
CASE_AND_STREAM ( s , SHT_REL , kStrWidth ) ;
CASE_AND_STREAM ( s , SHT_SHLIB , kStrWidth ) ;
CASE_AND_STREAM ( s , SHT_DYNSYM , kStrWidth ) ;
CASE_AND_STREAM ( s , SHT_LOPROC , kStrWidth ) ;
CASE_AND_STREAM ( s , SHT_HIPROC , kStrWidth ) ;
CASE_AND_STREAM ( s , SHT_LOUSER , kStrWidth ) ;
CASE_AND_STREAM ( s , SHT_HIUSER , kStrWidth ) ;
default :
s - > Printf ( " 0x%8.8x%*s " , sh_type , kStrWidth - 10 , " " ) ;
break ;
}
}
//----------------------------------------------------------------------
// DumpELFSectionHeader_sh_flags
//
// Dump an token value for the ELF section header member sh_flags
//----------------------------------------------------------------------
void
2013-01-25 18:06:21 +00:00
ObjectFileELF : : DumpELFSectionHeader_sh_flags ( Stream * s , elf_xword sh_flags )
2010-06-08 16:52:24 +00:00
{
* s < < ( ( sh_flags & SHF_WRITE ) ? " WRITE " : " " )
< < ( ( ( sh_flags & SHF_WRITE ) & & ( sh_flags & SHF_ALLOC ) ) ? ' + ' : ' ' )
< < ( ( sh_flags & SHF_ALLOC ) ? " ALLOC " : " " )
< < ( ( ( sh_flags & SHF_ALLOC ) & & ( sh_flags & SHF_EXECINSTR ) ) ? ' + ' : ' ' )
< < ( ( sh_flags & SHF_EXECINSTR ) ? " EXECINSTR " : " " ) ;
}
2010-07-13 23:07:23 +00:00
2010-06-08 16:52:24 +00:00
//----------------------------------------------------------------------
// DumpELFSectionHeaders
//
// Dump all of the ELF section header to the specified output stream
//----------------------------------------------------------------------
void
ObjectFileELF : : DumpELFSectionHeaders ( Stream * s )
{
2013-07-01 19:45:50 +00:00
if ( ! ParseSectionHeaders ( ) )
2010-07-13 23:07:23 +00:00
return ;
s - > PutCString ( " Section Headers \n " ) ;
s - > PutCString ( " IDX name type flags "
" addr offset size link info addralgn "
" entsize Name \n " ) ;
s - > PutCString ( " ==== -------- ------------ -------------------------------- "
" -------- -------- -------- -------- -------- -------- "
" -------- ==================== \n " ) ;
uint32_t idx = 0 ;
for ( SectionHeaderCollConstIter I = m_section_headers . begin ( ) ;
I ! = m_section_headers . end ( ) ; + + I , + + idx )
2010-06-08 16:52:24 +00:00
{
2010-07-13 23:07:23 +00:00
s - > Printf ( " [%2u] " , idx ) ;
ObjectFileELF : : DumpELFSectionHeader ( s , * I ) ;
2013-07-01 19:45:50 +00:00
const char * section_name = I - > section_name . AsCString ( " " ) ;
2010-07-13 23:07:23 +00:00
if ( section_name )
* s < < ' ' < < section_name < < " \n " ;
}
}
2010-06-08 16:52:24 +00:00
2010-07-13 23:07:23 +00:00
void
ObjectFileELF : : DumpDependentModules ( lldb_private : : Stream * s )
{
size_t num_modules = ParseDependentModules ( ) ;
2010-06-08 16:52:24 +00:00
2010-07-13 23:07:23 +00:00
if ( num_modules > 0 )
{
s - > PutCString ( " Dependent Modules: \n " ) ;
for ( unsigned i = 0 ; i < num_modules ; + + i )
2010-06-08 16:52:24 +00:00
{
2010-07-13 23:07:23 +00:00
const FileSpec & spec = m_filespec_ap - > GetFileSpecAtIndex ( i ) ;
s - > Printf ( " %s \n " , spec . GetFilename ( ) . GetCString ( ) ) ;
2010-06-08 16:52:24 +00:00
}
}
}
bool
2011-02-15 21:59:32 +00:00
ObjectFileELF : : GetArchitecture ( ArchSpec & arch )
2010-06-08 16:52:24 +00:00
{
2011-02-24 19:16:15 +00:00
if ( ! ParseHeader ( ) )
return false ;
2014-07-11 15:43:51 +00:00
if ( m_section_headers . empty ( ) )
{
// Allow elf notes to be parsed which may affect the detected architecture.
ParseSectionHeaders ( ) ;
}
2014-06-27 16:52:49 +00:00
arch = m_arch_spec ;
2010-07-13 23:07:23 +00:00
return true ;
2010-06-08 16:52:24 +00:00
}
2011-07-09 00:41:34 +00:00
ObjectFile : : Type
ObjectFileELF : : CalculateType ( )
{
switch ( m_header . e_type )
{
case llvm : : ELF : : ET_NONE :
// 0 - No file type
return eTypeUnknown ;
case llvm : : ELF : : ET_REL :
// 1 - Relocatable file
return eTypeObjectFile ;
case llvm : : ELF : : ET_EXEC :
// 2 - Executable file
return eTypeExecutable ;
case llvm : : ELF : : ET_DYN :
// 3 - Shared object file
return eTypeSharedLibrary ;
case ET_CORE :
// 4 - Core file
return eTypeCoreFile ;
default :
break ;
}
return eTypeUnknown ;
}
ObjectFile : : Strata
ObjectFileELF : : CalculateStrata ( )
{
switch ( m_header . e_type )
{
case llvm : : ELF : : ET_NONE :
// 0 - No file type
return eStrataUnknown ;
case llvm : : ELF : : ET_REL :
// 1 - Relocatable file
return eStrataUnknown ;
case llvm : : ELF : : ET_EXEC :
// 2 - Executable file
// TODO: is there any way to detect that an executable is a kernel
// related executable by inspecting the program headers, section
// headers, symbols, or any other flag bits???
return eStrataUser ;
case llvm : : ELF : : ET_DYN :
// 3 - Shared object file
// TODO: is there any way to detect that an shared library is a kernel
// related executable by inspecting the program headers, section
// headers, symbols, or any other flag bits???
return eStrataUnknown ;
case ET_CORE :
// 4 - Core file
// TODO: is there any way to detect that an core file is a kernel
// related executable by inspecting the program headers, section
// headers, symbols, or any other flag bits???
return eStrataUnknown ;
default :
break ;
}
return eStrataUnknown ;
}