Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
2dot5
ClickHouse
提交
957b59f0
C
ClickHouse
项目概览
2dot5
/
ClickHouse
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
ClickHouse
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
957b59f0
编写于
7月 29, 2019
作者:
A
Alexey Milovidov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Cleanups
上级
300d2525
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
208 addition
and
112 deletion
+208
-112
dbms/src/Common/Elf.cpp
dbms/src/Common/Elf.cpp
+121
-0
dbms/src/Common/Elf.h
dbms/src/Common/Elf.h
+57
-0
dbms/src/Common/ErrorCodes.cpp
dbms/src/Common/ErrorCodes.cpp
+1
-0
dbms/src/Common/SymbolIndex.cpp
dbms/src/Common/SymbolIndex.cpp
+28
-111
dbms/src/Common/SymbolIndex.h
dbms/src/Common/SymbolIndex.h
+1
-1
未找到文件。
dbms/src/Common/Elf.cpp
0 → 100644
浏览文件 @
957b59f0
#include <Common/Elf.h>
#include <Common/Exception.h>
#include <iostream>
namespace
DB
{
namespace
ErrorCodes
{
extern
const
int
CANNOT_PARSE_ELF
;
}
Elf
::
Elf
(
const
std
::
string
&
path
)
:
in
(
path
,
0
)
{
std
::
cerr
<<
"Processing path "
<<
path
<<
"
\n
"
;
/// Check if it's an elf.
size
=
in
.
buffer
().
size
();
if
(
size
<
sizeof
(
ElfEhdr
))
throw
Exception
(
"The size of supposedly ELF file is too small"
,
ErrorCodes
::
CANNOT_PARSE_ELF
);
mapped
=
in
.
buffer
().
begin
();
header
=
reinterpret_cast
<
const
ElfEhdr
*>
(
mapped
);
if
(
memcmp
(
header
->
e_ident
,
"
\x7F
""ELF"
,
4
)
!=
0
)
throw
Exception
(
"The file is not ELF according to magic"
,
ErrorCodes
::
CANNOT_PARSE_ELF
);
/// Get section header.
ElfOff
section_header_offset
=
header
->
e_shoff
;
uint16_t
section_header_num_entries
=
header
->
e_shnum
;
if
(
!
section_header_offset
||
!
section_header_num_entries
||
section_header_offset
+
section_header_num_entries
*
sizeof
(
ElfShdr
)
>
size
)
throw
Exception
(
"The ELF is truncated (section header points after end of file)"
,
ErrorCodes
::
CANNOT_PARSE_ELF
);
section_headers
=
reinterpret_cast
<
const
ElfShdr
*>
(
mapped
+
section_header_offset
);
/// The string table with section names.
auto
section_names_strtab
=
findSection
([
&
](
const
Section
&
section
,
size_t
idx
)
{
return
section
.
header
.
sh_type
==
SHT_STRTAB
&&
header
->
e_shstrndx
==
idx
;
});
if
(
!
section_names_strtab
)
throw
Exception
(
"The ELF doesn't have string table with section names"
,
ErrorCodes
::
CANNOT_PARSE_ELF
);
ElfOff
section_names_offset
=
section_names_strtab
->
header
.
sh_offset
;
if
(
section_names_offset
>=
size
)
throw
Exception
(
"The ELF is truncated (section names string table points after end of file)"
,
ErrorCodes
::
CANNOT_PARSE_ELF
);
section_names
=
reinterpret_cast
<
const
char
*>
(
mapped
+
section_names_offset
);
}
Elf
::
Section
::
Section
(
const
ElfShdr
&
header
,
const
Elf
&
elf
)
:
header
(
header
),
elf
(
elf
)
{
}
bool
Elf
::
iterateSections
(
std
::
function
<
bool
(
const
Section
&
section
,
size_t
idx
)
>
&&
pred
)
const
{
for
(
size_t
idx
=
0
;
idx
<
header
->
e_shnum
;
++
idx
)
{
Section
section
(
section_headers
[
idx
],
*
this
);
/// Sections spans after end of file.
if
(
section
.
header
.
sh_offset
+
section
.
header
.
sh_size
>
size
)
continue
;
if
(
pred
(
section
,
idx
))
return
true
;
}
return
false
;
}
std
::
optional
<
Elf
::
Section
>
Elf
::
findSection
(
std
::
function
<
bool
(
const
Section
&
section
,
size_t
idx
)
>
&&
pred
)
const
{
std
::
optional
<
Elf
::
Section
>
result
;
iterateSections
([
&
](
const
Section
&
section
,
size_t
idx
)
{
if
(
pred
(
section
,
idx
))
{
result
.
emplace
(
section
);
return
true
;
}
return
false
;
});
return
result
;
}
const
char
*
Elf
::
Section
::
name
()
const
{
if
(
!
elf
.
section_names
)
throw
Exception
(
"Section names are not initialized"
,
ErrorCodes
::
CANNOT_PARSE_ELF
);
/// TODO buffer overflow is possible, we may need to check strlen.
return
elf
.
section_names
+
header
.
sh_name
;
}
const
char
*
Elf
::
Section
::
begin
()
const
{
return
elf
.
mapped
+
header
.
sh_offset
;
}
const
char
*
Elf
::
Section
::
end
()
const
{
return
elf
.
mapped
+
header
.
sh_offset
+
header
.
sh_size
;
}
}
dbms/src/Common/Elf.h
0 → 100644
浏览文件 @
957b59f0
#pragma once
#include <IO/MMapReadBufferFromFile.h>
#include <string>
#include <optional>
#include <functional>
#include <elf.h>
#include <link.h>
using
ElfAddr
=
ElfW
(
Addr
);
using
ElfEhdr
=
ElfW
(
Ehdr
);
using
ElfOff
=
ElfW
(
Off
);
using
ElfPhdr
=
ElfW
(
Phdr
);
using
ElfShdr
=
ElfW
(
Shdr
);
using
ElfSym
=
ElfW
(
Sym
);
namespace
DB
{
class
Elf
{
public:
struct
Section
{
const
ElfShdr
&
header
;
const
char
*
name
()
const
;
const
char
*
begin
()
const
;
const
char
*
end
()
const
;
Section
(
const
ElfShdr
&
header
,
const
Elf
&
elf
);
private:
const
Elf
&
elf
;
};
Elf
(
const
std
::
string
&
path
);
std
::
optional
<
Section
>
findSection
(
std
::
function
<
bool
(
const
Section
&
section
,
size_t
idx
)
>
&&
pred
)
const
;
bool
iterateSections
(
std
::
function
<
bool
(
const
Section
&
section
,
size_t
idx
)
>
&&
pred
)
const
;
const
char
*
end
()
const
{
return
mapped
+
size
;
}
private:
MMapReadBufferFromFile
in
;
size_t
size
;
const
char
*
mapped
;
const
ElfEhdr
*
header
;
const
ElfShdr
*
section_headers
;
const
char
*
section_names
=
nullptr
;
};
}
dbms/src/Common/ErrorCodes.cpp
浏览文件 @
957b59f0
...
...
@@ -438,6 +438,7 @@ namespace ErrorCodes
extern
const
int
CANNOT_SET_TIMER_PERIOD
=
461
;
extern
const
int
CANNOT_DELETE_TIMER
=
462
;
extern
const
int
CANNOT_FCNTL
=
463
;
extern
const
int
CANNOT_PARSE_ELF
=
464
;
extern
const
int
KEEPER_EXCEPTION
=
999
;
extern
const
int
POCO_EXCEPTION
=
1000
;
...
...
dbms/src/Common/SymbolIndex.cpp
浏览文件 @
957b59f0
#include <Common/SymbolIndex.h>
#include <
IO/MMapReadBufferFromFile
.h>
#include <
Common/Elf
.h>
#include <common/demangle.h>
#include <algorithm>
...
...
@@ -162,39 +162,28 @@ void collectSymbolsFromProgramHeaders(dl_phdr_info * info, std::vector<DB::Symbo
void
collectSymbolsFromELFSymbolTable
(
dl_phdr_info
*
info
,
const
char
*
mapped_elf
,
size_t
elf_size
,
const
ElfW
(
Shdr
)
*
symbol_table
,
const
ElfW
(
Shdr
)
*
string_table
,
const
DB
::
Elf
&
elf
,
const
DB
::
Elf
::
Section
&
symbol_table
,
const
DB
::
Elf
::
Section
&
string_table
,
std
::
vector
<
DB
::
SymbolIndex
::
Symbol
>
&
symbols
)
{
if
(
symbol_table
->
sh_offset
+
symbol_table
->
sh_size
>
elf_size
||
string_table
->
sh_offset
+
string_table
->
sh_size
>
elf_size
)
return
;
/// Iterate symbol table.
const
ElfW
(
Sym
)
*
symbol_table_entry
=
reinterpret_cast
<
const
ElfW
(
Sym
)
*>
(
mapped_elf
+
symbol_table
->
sh_offset
);
const
ElfW
(
Sym
)
*
symbol_table_end
=
reinterpret_cast
<
const
ElfW
(
Sym
)
*>
(
mapped_elf
+
symbol_table
->
sh_offset
+
symbol_table
->
sh_size
);
// std::cerr << "Symbol table has: " << (symbol_table_end - symbol_table_entry) << "\n";
const
ElfSym
*
symbol_table_entry
=
reinterpret_cast
<
const
ElfSym
*>
(
symbol_table
.
begin
());
const
ElfSym
*
symbol_table_end
=
reinterpret_cast
<
const
ElfSym
*>
(
symbol_table
.
end
());
const
char
*
strings
=
reinterpret_cast
<
const
char
*>
(
mapped_elf
+
string_table
->
sh_offset
);
const
char
*
strings
=
string_table
.
begin
(
);
for
(;
symbol_table_entry
<
symbol_table_end
;
++
symbol_table_entry
)
{
if
(
!
symbol_table_entry
->
st_name
||
!
symbol_table_entry
->
st_value
||
!
symbol_table_entry
->
st_size
||
string
_table
->
sh_offset
+
symbol_table_entry
->
st_name
>=
elf_size
)
||
string
s
+
symbol_table_entry
->
st_name
>=
elf
.
end
()
)
continue
;
// std::cerr << "Symbol Ok" << "\n";
/// Find the name in strings table.
const
char
*
symbol_name
=
strings
+
symbol_table_entry
->
st_name
;
// std::cerr << "Symbol name: " << symbol_name << "\n";
DB
::
SymbolIndex
::
Symbol
symbol
;
symbol
.
address_begin
=
reinterpret_cast
<
const
void
*>
(
info
->
dlpi_addr
+
symbol_table_entry
->
st_value
);
symbol
.
address_end
=
reinterpret_cast
<
const
void
*>
(
info
->
dlpi_addr
+
symbol_table_entry
->
st_value
+
symbol_table_entry
->
st_size
);
...
...
@@ -207,45 +196,32 @@ void collectSymbolsFromELFSymbolTable(
}
bool
c
ollectSymbolsFromELFSymbolTable
(
bool
searchAndC
ollectSymbolsFromELFSymbolTable
(
dl_phdr_info
*
info
,
const
char
*
mapped_elf
,
size_t
elf_size
,
const
ElfW
(
Shdr
)
*
section_headers
,
size_t
section_header_num_entries
,
ElfW
(
Off
)
section_names_offset
,
const
char
*
section_names
,
ElfW
(
Word
)
section_header_type
,
const
DB
::
Elf
&
elf
,
unsigned
section_header_type
,
const
char
*
string_table_name
,
std
::
vector
<
DB
::
SymbolIndex
::
Symbol
>
&
symbols
)
{
const
ElfW
(
Shdr
)
*
symbol_table
=
nullptr
;
const
ElfW
(
Shdr
)
*
string_table
=
nullptr
;
std
::
optional
<
DB
::
Elf
::
Section
>
symbol_table
;
std
::
optional
<
DB
::
Elf
::
Section
>
string_table
;
for
(
size_t
section_header_idx
=
0
;
section_header_idx
<
section_header_num_entries
;
++
section_header_idx
)
{
auto
&
entry
=
section_headers
[
section_header_idx
];
// std::cerr << entry.sh_type << ", " << (section_names + entry.sh_name) << "\n";
if
(
!
elf
.
iterateSections
([
&
](
const
DB
::
Elf
::
Section
&
section
,
size_t
)
{
if
(
section
.
header
.
sh_type
==
section_header_type
)
symbol_table
.
emplace
(
section
);
else
if
(
section
.
header
.
sh_type
==
SHT_STRTAB
&&
0
==
strcmp
(
section
.
name
(),
string_table_name
))
string_table
.
emplace
(
section
);
if
(
section_names_offset
+
entry
.
sh_name
>=
elf_size
)
if
(
symbol_table
&&
string_table
)
return
true
;
return
false
;
if
(
entry
.
sh_type
==
section_header_type
)
symbol_table
=
&
entry
;
else
if
(
entry
.
sh_type
==
SHT_STRTAB
&&
0
==
strcmp
(
section_names
+
entry
.
sh_name
,
string_table_name
))
string_table
=
&
entry
;
if
(
symbol_table
&&
string_table
)
break
;
}
if
(
!
symbol_table
||
!
string_table
)
}))
{
return
false
;
}
// std::cerr << "Found tables for " << string_table_name << "\n";
collectSymbolsFromELFSymbolTable
(
info
,
mapped_elf
,
elf_size
,
symbol_table
,
string_table
,
symbols
);
collectSymbolsFromELFSymbolTable
(
info
,
elf
,
*
symbol_table
,
*
string_table
,
symbols
);
return
true
;
}
...
...
@@ -266,69 +242,10 @@ void collectSymbolsFromELF(dl_phdr_info * info, std::vector<DB::SymbolIndex::Sym
if
(
ec
)
return
;
// std::cerr << object_name << "\n";
/// Read elf file.
DB
::
MMapReadBufferFromFile
in
(
object_name
,
0
);
/// Check if it's an elf.
size_t
elf_size
=
in
.
buffer
().
size
();
if
(
elf_size
<
sizeof
(
ElfW
(
Ehdr
)))
return
;
// std::cerr << "Size Ok" << "\n";
const
char
*
mapped_elf
=
in
.
buffer
().
begin
();
const
ElfW
(
Ehdr
)
*
elf_header
=
reinterpret_cast
<
const
ElfW
(
Ehdr
)
*>
(
mapped_elf
);
if
(
memcmp
(
elf_header
->
e_ident
,
"
\x7F
""ELF"
,
4
)
!=
0
)
return
;
// std::cerr << "Header Ok" << "\n";
/// Get section header.
ElfW
(
Off
)
section_header_offset
=
elf_header
->
e_shoff
;
uint16_t
section_header_num_entries
=
elf_header
->
e_shnum
;
// std::cerr << section_header_offset << ", " << section_header_num_entries << ", " << (section_header_num_entries * sizeof(ElfW(Shdr))) << ", " << elf_size << "\n";
if
(
!
section_header_offset
||
!
section_header_num_entries
||
section_header_offset
+
section_header_num_entries
*
sizeof
(
ElfW
(
Shdr
))
>
elf_size
)
return
;
// std::cerr << "Section header Ok" << "\n";
/// Find symtab, strtab or dyndym, dynstr.
const
ElfW
(
Shdr
)
*
section_headers
=
reinterpret_cast
<
const
ElfW
(
Shdr
)
*>
(
mapped_elf
+
section_header_offset
);
/// The string table with section names.
ElfW
(
Off
)
section_names_offset
=
0
;
const
char
*
section_names
=
nullptr
;
for
(
size_t
section_header_idx
=
0
;
section_header_idx
<
section_header_num_entries
;
++
section_header_idx
)
{
auto
&
entry
=
section_headers
[
section_header_idx
];
if
(
entry
.
sh_type
==
SHT_STRTAB
&&
elf_header
->
e_shstrndx
==
section_header_idx
)
{
// std::cerr << "Found section names\n";
section_names_offset
=
entry
.
sh_offset
;
if
(
section_names_offset
>=
elf_size
)
return
;
section_names
=
reinterpret_cast
<
const
char
*>
(
mapped_elf
+
section_names_offset
);
break
;
}
}
if
(
!
section_names
)
return
;
collectSymbolsFromELFSymbolTable
(
info
,
mapped_elf
,
elf_size
,
section_headers
,
section_header_num_entries
,
section_names_offset
,
section_names
,
SHT_SYMTAB
,
".strtab"
,
symbols
);
DB
::
Elf
elf
(
object_name
);
collectSymbolsFromELFSymbolTable
(
info
,
mapped_elf
,
elf_size
,
section_headers
,
section_header_num_entries
,
section_names_offset
,
section_names
,
SHT_DYNSYM
,
".dynstr"
,
symbols
);
searchAndCollectSymbolsFromELFSymbolTable
(
info
,
elf
,
SHT_SYMTAB
,
".strtab"
,
symbols
);
searchAndCollectSymbolsFromELFSymbolTable
(
info
,
elf
,
SHT_DYNSYM
,
".dynstr"
,
symbols
);
}
...
...
dbms/src/Common/SymbolIndex.h
浏览文件 @
957b59f0
...
...
@@ -18,7 +18,7 @@ public:
const
void
*
address_begin
;
const
void
*
address_end
;
const
char
*
object
;
std
::
string
name
;
/// demangled
std
::
string
name
;
/// demangled
NOTE Can use Arena for strings
bool
operator
<
(
const
Symbol
&
rhs
)
const
{
return
address_begin
<
rhs
.
address_begin
;
}
bool
operator
<
(
const
void
*
addr
)
const
{
return
address_begin
<=
addr
;
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录