mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-27 01:51:59 +00:00
Merge pull request #33264 from azat/symbols-from-resources-fix
Fix parsing symbols from resources (for shared builds)
This commit is contained in:
commit
3655965b39
@ -86,7 +86,7 @@ namespace
|
|||||||
/// https://stackoverflow.com/questions/32088140/multiple-string-tables-in-elf-object
|
/// https://stackoverflow.com/questions/32088140/multiple-string-tables-in-elf-object
|
||||||
|
|
||||||
|
|
||||||
void updateResources(std::string_view name, const void * address, SymbolIndex::Resources & resources)
|
void updateResources(ElfW(Addr) base_address, std::string_view object_name, std::string_view name, const void * address, SymbolIndex::Resources & resources)
|
||||||
{
|
{
|
||||||
const char * char_address = static_cast<const char *>(address);
|
const char * char_address = static_cast<const char *>(address);
|
||||||
|
|
||||||
@ -97,18 +97,23 @@ void updateResources(std::string_view name, const void * address, SymbolIndex::R
|
|||||||
name = name.substr((name[0] == '_') + strlen("binary_"));
|
name = name.substr((name[0] == '_') + strlen("binary_"));
|
||||||
name = name.substr(0, name.size() - strlen("_start"));
|
name = name.substr(0, name.size() - strlen("_start"));
|
||||||
|
|
||||||
resources.emplace(name, std::string_view{char_address, 0}); // NOLINT
|
resources.emplace(name, SymbolIndex::ResourcesBlob{
|
||||||
|
base_address,
|
||||||
|
object_name,
|
||||||
|
std::string_view{char_address, 0}, // NOLINT
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else if (name.ends_with("_end"))
|
else if (name.ends_with("_end"))
|
||||||
{
|
{
|
||||||
name = name.substr((name[0] == '_') + strlen("binary_"));
|
name = name.substr((name[0] == '_') + strlen("binary_"));
|
||||||
name = name.substr(0, name.size() - strlen("_end"));
|
name = name.substr(0, name.size() - strlen("_end"));
|
||||||
|
|
||||||
if (auto it = resources.find(name); it != resources.end() && it->second.empty())
|
auto it = resources.find(name);
|
||||||
|
if (it != resources.end() && it->second.base_address == base_address && it->second.data.empty())
|
||||||
{
|
{
|
||||||
const char * start = it->second.data();
|
const char * start = it->second.data.data();
|
||||||
assert(char_address >= start);
|
assert(char_address >= start);
|
||||||
it->second = std::string_view{start, static_cast<size_t>(char_address - start)};
|
it->second.data = std::string_view{start, static_cast<size_t>(char_address - start)};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -153,10 +158,12 @@ void collectSymbolsFromProgramHeaders(
|
|||||||
size_t sym_cnt = 0;
|
size_t sym_cnt = 0;
|
||||||
for (const auto * it = dyn_begin; it->d_tag != DT_NULL; ++it)
|
for (const auto * it = dyn_begin; it->d_tag != DT_NULL; ++it)
|
||||||
{
|
{
|
||||||
|
ElfW(Addr) base_address = correct_address(info->dlpi_addr, it->d_un.d_ptr);
|
||||||
|
|
||||||
// TODO: this branch leads to invalid address of the hash table. Need further investigation.
|
// TODO: this branch leads to invalid address of the hash table. Need further investigation.
|
||||||
// if (it->d_tag == DT_HASH)
|
// if (it->d_tag == DT_HASH)
|
||||||
// {
|
// {
|
||||||
// const ElfW(Word) * hash = reinterpret_cast<const ElfW(Word) *>(correct_address(info->dlpi_addr, it->d_un.d_ptr));
|
// const ElfW(Word) * hash = reinterpret_cast<const ElfW(Word) *>(base_address);
|
||||||
// sym_cnt = hash[1];
|
// sym_cnt = hash[1];
|
||||||
// break;
|
// break;
|
||||||
// }
|
// }
|
||||||
@ -167,7 +174,7 @@ void collectSymbolsFromProgramHeaders(
|
|||||||
const uint32_t * buckets = nullptr;
|
const uint32_t * buckets = nullptr;
|
||||||
const uint32_t * hashval = nullptr;
|
const uint32_t * hashval = nullptr;
|
||||||
|
|
||||||
const ElfW(Word) * hash = reinterpret_cast<const ElfW(Word) *>(correct_address(info->dlpi_addr, it->d_un.d_ptr));
|
const ElfW(Word) * hash = reinterpret_cast<const ElfW(Word) *>(base_address);
|
||||||
|
|
||||||
buckets = hash + 4 + (hash[2] * sizeof(size_t) / 4);
|
buckets = hash + 4 + (hash[2] * sizeof(size_t) / 4);
|
||||||
|
|
||||||
@ -196,9 +203,11 @@ void collectSymbolsFromProgramHeaders(
|
|||||||
const char * strtab = nullptr;
|
const char * strtab = nullptr;
|
||||||
for (const auto * it = dyn_begin; it->d_tag != DT_NULL; ++it)
|
for (const auto * it = dyn_begin; it->d_tag != DT_NULL; ++it)
|
||||||
{
|
{
|
||||||
|
ElfW(Addr) base_address = correct_address(info->dlpi_addr, it->d_un.d_ptr);
|
||||||
|
|
||||||
if (it->d_tag == DT_STRTAB)
|
if (it->d_tag == DT_STRTAB)
|
||||||
{
|
{
|
||||||
strtab = reinterpret_cast<const char *>(correct_address(info->dlpi_addr, it->d_un.d_ptr));
|
strtab = reinterpret_cast<const char *>(base_address);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -208,10 +217,12 @@ void collectSymbolsFromProgramHeaders(
|
|||||||
|
|
||||||
for (const auto * it = dyn_begin; it->d_tag != DT_NULL; ++it)
|
for (const auto * it = dyn_begin; it->d_tag != DT_NULL; ++it)
|
||||||
{
|
{
|
||||||
|
ElfW(Addr) base_address = correct_address(info->dlpi_addr, it->d_un.d_ptr);
|
||||||
|
|
||||||
if (it->d_tag == DT_SYMTAB)
|
if (it->d_tag == DT_SYMTAB)
|
||||||
{
|
{
|
||||||
/* Get the pointer to the first entry of the symbol table */
|
/* Get the pointer to the first entry of the symbol table */
|
||||||
const ElfW(Sym) * elf_sym = reinterpret_cast<const ElfW(Sym) *>(correct_address(info->dlpi_addr, it->d_un.d_ptr));
|
const ElfW(Sym) * elf_sym = reinterpret_cast<const ElfW(Sym) *>(base_address);
|
||||||
|
|
||||||
/* Iterate over the symbol table */
|
/* Iterate over the symbol table */
|
||||||
for (ElfW(Word) sym_index = 0; sym_index < ElfW(Word)(sym_cnt); ++sym_index)
|
for (ElfW(Word) sym_index = 0; sym_index < ElfW(Word)(sym_cnt); ++sym_index)
|
||||||
@ -236,7 +247,7 @@ void collectSymbolsFromProgramHeaders(
|
|||||||
symbols.push_back(symbol);
|
symbols.push_back(symbol);
|
||||||
|
|
||||||
/// But resources can be represented by a pair of empty symbols (indicating their boundaries).
|
/// But resources can be represented by a pair of empty symbols (indicating their boundaries).
|
||||||
updateResources(symbol.name, symbol.address_begin, resources);
|
updateResources(base_address, info->dlpi_name, symbol.name, symbol.address_begin, resources);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -299,7 +310,7 @@ void collectSymbolsFromELFSymbolTable(
|
|||||||
if (symbol_table_entry->st_size)
|
if (symbol_table_entry->st_size)
|
||||||
symbols.push_back(symbol);
|
symbols.push_back(symbol);
|
||||||
|
|
||||||
updateResources(symbol.name, symbol.address_begin, resources);
|
updateResources(info->dlpi_addr, info->dlpi_name, symbol.name, symbol.address_begin, resources);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ public:
|
|||||||
std::string_view getResource(String name) const
|
std::string_view getResource(String name) const
|
||||||
{
|
{
|
||||||
if (auto it = data.resources.find(name); it != data.resources.end())
|
if (auto it = data.resources.find(name); it != data.resources.end())
|
||||||
return it->second;
|
return it->second.data;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +59,17 @@ public:
|
|||||||
String getBuildID() const { return data.build_id; }
|
String getBuildID() const { return data.build_id; }
|
||||||
String getBuildIDHex() const;
|
String getBuildIDHex() const;
|
||||||
|
|
||||||
using Resources = std::unordered_map<std::string_view /* symbol name */, std::string_view /* blob */>;
|
struct ResourcesBlob
|
||||||
|
{
|
||||||
|
/// Symbol can be presented in multiple shared objects,
|
||||||
|
/// base_address will be used to compare only symbols from the same SO.
|
||||||
|
ElfW(Addr) base_address;
|
||||||
|
/// Just a human name of the SO.
|
||||||
|
std::string_view object_name;
|
||||||
|
/// Data blob.
|
||||||
|
std::string_view data;
|
||||||
|
};
|
||||||
|
using Resources = std::unordered_map<std::string_view /* symbol name */, ResourcesBlob>;
|
||||||
|
|
||||||
struct Data
|
struct Data
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user