Tmux
导言
默认安装了ohmytmux时的常见命令。
常用命令
默认的tmux快捷键
- 退出 :输入 exit 或按下 Ctrl + D 关闭当前的 tmux 窗口或面板。
Useful to copy
<prefix> +
maximizes the current pane to a new window
默认安装了ohmytmux时的常见命令。
默认的tmux快捷键
<prefix> +
maximizes the current pane to a new window
全体选项其中一部分是Optimize-Options
编译时最好按照其分类有效组织, 例子如下:
g++
# Warning Options
-Wall -Werror -Wno-unknown-pragmas -Wno-dangling-pointer
# Program Instrumentation Options
-fno-stack-protector
# Code-Gen-Options
-fno-exceptions -funwind-tables -fasynchronous-unwind-tables
# C++ Dialect
-fabi-version=2 -faligned-new -fno-rtti
# define
-DPIN_CRT=1 -DTARGET_IA32E -DHOST_IA32E -fPIC -DTARGET_LINUX
# include
-I../../../source/include/pin
-I../../../source/include/pin/gen
-isystem /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/cxx/include
-isystem /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/crt/include
-isystem /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/crt/include/arch-x86_64
-isystem /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/crt/include/kernel/uapi
-isystem /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/crt/include/kernel/uapi/asm-x86
-I../../../extras/components/include
-I../../../extras/xed-intel64/include/xed
-I../../../source/tools/Utils
-I../../../source/tools/InstLib
# Optimization Options
-O3 -fomit-frame-pointer -fno-strict-aliasing
-c -o obj-intel64/inscount0.o inscount0.cpp
-Wxxx
对 xxx 启动warning, -fxxx
启动xxx的编译器功能。-fno-xxx
关闭对应选项???-gxxx
debug 相关-mxxx
特定机器架构的选项名称 | 含义 |
---|---|
-Wall | 打开常见的所有warning选项 |
-Werror | 把warning当成error |
-std= | C or C++ language standard. eg 'c++11' == 'c++0x' 'c++17' == 'c++1z', which 'c++0x','c++17' is develop codename |
-Wunknown-pragmas | 未知的pragma会报错(-Wno-unknown-pragmas 应该是相反的) |
-fomit-frame-pointer | 不生成栈帧指针,属于-O1优化 |
-Wstack-protector | 没有防止堆栈崩溃的函数时warning (-fno-stack-protector) |
-MMD | only user header files, not system header files. |
-fexceptions | Enable exception handling. |
-funwind-tables | Unwind tables contain debug frame information which is also necessary for the handling of such exceptions |
-fasynchronous-unwind-tables | Generate unwind table in DWARF format. so it can be used for stack unwinding from asynchronous events |
-fabi-version=n | Use version n of the C++ ABI. The default is version 0.(Version 2 is the version of the C++ ABI that first appeared in G++ 3.4, and was the default through G++ 4.9.) ABI: an application binary interface (ABI) is an interface between two binary program modules. Often, one of these modules is a library or operating system facility, and the other is a program that is being run by a user. |
-fno-rtti | Disable generation of information about every class with virtual functions for use by the C++ run-time type identification features (dynamic_cast and typeid). If you don’t use those parts of the language, you can save some space by using this flag |
-faligned-new | Enable support for C++17 new of types that require more alignment than void* ::operator new(std::size_t) provides. A numeric argument such as -faligned-new=32 can be used to specify how much alignment (in bytes) is provided by that function, but few users will need to override the default of alignof(std::max_align_t) . This flag is enabled by default for -std=c++17 . |
-Wl, xxx | pass xxx option to linker, e.g., -Wl,-R/staff/shaojiemike/github/MultiPIM_icarus0/common/libconfig/lib specify a runtime library search path for dynamic libraries (shared libraries) during the linking process. |
-O3 turns on all optimizations specified by -O2
and also turns on the -finline-functions, -funswitch-loops, -fpredictive-commoning, -fgcse-after-reload, -ftree-loop-vectorize, -ftree-loop-distribute-patterns, -ftree-slp-vectorize, -fvect-cost-model, -ftree-partial-pre and -fipa-cp-clone options
允许使用浮点计算获得更高的性能,但可能会略微降低精度。
更快但是有保证正确
(仅限 GNU)链接时优化,当程序链接时检查文件之间的函数调用的步骤。该标志必须用于编译和链接时。使用此标志的编译时间很长,但是根据应用程序,当与 -O* 标志结合使用时,可能会有明显的性能改进。这个标志和任何优化标志都必须传递给链接器,并且应该调用 gcc/g++/gfortran 进行链接而不是直接调用 ld。
此标志对特定处理器类型进行额外调整,但它不会生成额外的 SIMD 指令,因此不存在体系结构兼容性问题。调整将涉及对处理器缓存大小、首选指令顺序等的优化。
在 AMD Bulldozer 节点上使用的值为 bdver1,在 AMD Epyc 节点上使用的值为 znver2。是zen ver2的简称。
-fprefetch-loop-arrays
-Os
禁用https://zhuanlan.zhihu.com/p/496435946
下面没有特别指明都是O3,默认开启
-ftree-loop-distribution
-ftree-loop-distribute-patterns
-floop-interchange
-floop-unroll-and-jam
(不是计算访问的数据)
-falign-functions=n:m:n2:m2
-freorder-blocks
Unroll loops whose number of iterations can be determined at compile time or upon entry to the loop. -funroll-loops
implies -frerun-cse-after-loop
. This option makes code larger, and may or may not make it run faster.
Unroll all loops, even if their number of iterations is uncertain when the loop is entered. This usually makes programs run more slowly. -funroll-all-loops
implies the same options as -funroll-loops
,
The maximum number of instructions that a loop should have if that loop is unrolled, and if the loop is unrolled, it determines how many times the loop code is unrolled. 如果循环被展开,则循环应具有的最大指令数,如果循环被展开,则它确定循环代码被展开的次数。
The maximum number of instructions biased by probabilities of their execution that a loop should have if that loop is unrolled, and if the loop is unrolled, it determines how many times the loop code is unrolled. 如果一个循环被展开,则根据其执行概率偏置的最大指令数,如果该循环被展开,则确定循环代码被展开的次数。
The maximum number of unrollings of a single loop. 单个循环的最大展开次数。
会自动检测,但有可能检测不对。
这将为特定架构生成 SIMD 指令并应用 -mtune 优化。 arch 的有用值与上面的 -mtune 标志相同。
g++ -march=native -m32 ... -Q --help=target
-mtune= skylake-avx512
Known valid arguments for -march= option:
i386 i486 i586 pentium lakemont pentium-mmx winchip-c6 winchip2 c3 samuel-2 c3-2 nehemiah c7 esther i686 pentiumpro pentium2 pentium3 pentium3m pentium-m pentium4 pentium4m prescott nocona core2 nehalem corei7 westmere sandybridge corei7-avx ivybridge core-avx-i haswell core-avx2 broadwell skylake skylake-avx512 cannonlake icelake-client icelake-server cascadelake tigerlake bonnell atom silvermont slm goldmont goldmont-plus tremont knl knm intel geode k6 k6-2 k6-3 athlon athlon-tbird athlon-4 athlon-xp athlon-mp x86-64 eden-x2 nano nano-1000 nano-2000 nano-3000 nano-x2 eden-x4 nano-x4 k8 k8-sse3 opteron opteron-sse3 athlon64 athlon64-sse3 athlon-fx amdfam10 barcelona bdver1 bdver2 bdver3 bdver4 znver1 znver2 btver1 btver2 generic native
position-independent code(PIC)
暂无
暂无
编译是指编译器读取源程序(字符流),对之进行词法和语法的分析,将高级语言指令转换为功能等效的汇编代码。
#include
语句以及一些宏插入程序文本中,得到main.i
和sum.i
文件。main.i
和sum.i
编译成文本文件main.s
和sum.c
的汇编语言程序。
低级的汇编语言为不同的高级语言提供了通用输出语言。main.s
和sum.s
翻译成机器语言的二进制指令,并打包成一种叫做可重定位目标程序的格式,并将结果保存在main.o和sum.o两个文件中。这种文件格式就比较接近elf格式了。main.o
和sum.o
,得到可执行目标文件,就是elf格式文件。
目标文件有三种形式:
.c
文件转化成 .i
文件.gcc –E filename.cpp -o filename.i
-E Preprocess only; do not compile, assemble or link.
-C
能保留头文件里的注释,如gcc -E -C circle.c -o circle.c
gcc -save-temps -c -o main.o main.c
cpp filename.cpp -o filename.i
命令linemarkers
类似# linenum filename flags
的注释,这些注释是为了让编译器能够定位到源文件的行号,以便于编译器能够在编译错误时给出正确的行号。flags
meaning除开注释被替换成空格,包括代码里的预处理命令:
#error "text"
的作用是在编译时生成一个错误消息,它会导致编译过程中断。 同理有#warning
#define a b
对于这种伪指令,预编译所要做的是将程序中的所有a用b替换,但作为字符串常量的 a则不被替换。还有 #undef,则将取消对某个宏的定义,使以后该串的出现不再被替换。#ifdef SNIPER
,#if defined SNIPER && SNIPER == 0
,#ifndef,#else,#elif,#endif等。 这些伪指令的引入使得程序员可以通过定义不同的宏来决定编译程序对哪些代码进行处理。预编译程序将根据有关的文件,将那些不必要的代码过滤掉-DSNIPER=5
#include "FileName"
或者#include 等。
该指令将头文件中的定义统统都加入到它所产生的输出文件中,以供编译程序对之进行处理。LINE
标识将被解释为当前行号(十进制数),FILE
则被解释为当前被编译的C源程序的名称。
预编译程序对于在源程序中出现的这些串将用合适的值进行替换。#include ""
vs #include <>
区别在于前者会在文件的当前目录寻找,但是后者只会在编译器编译的official路径寻找
通常的搜索顺序是:
#include
命令中以引号包括的文件名)。-iquote
选项指定的目录,依照出现在命令行中的顺序进行搜索。只对 #include
命令中采用引号的头文件名进行搜索。-I
开始, 依照出现在命令行中的顺序进行搜索。(可以使用-I/path/file
只添加一个头文件,尤其是在编译的兼容性修改时)-isystem
选项指定的目录,依照出现在命令行中的顺序进行搜索。C_INCLUDE_PATH,CPLUS_INCLUDE_PATH,OBJC_INCLUDE_PATH
指定的路径再找系统默认目录(/usr/include、/usr/local/include、/usr/lib/gcc-lib/i386-linux/2.95.2/include......)
通过如下命令可以查看头文件搜索目录 gcc -xc -E -v - < /dev/null
或者 g++ -xc++ -E -v - < /dev/null
*. 如果想改,需要重新编译gcc
g++ -H -v
查看是不是项目下的同名头文件优先级高于sys-head-file.c/.h
或者.i
文件转换成.s
文件,gcc –S filename.cpp -o filename.s
,对应于-S Compile only; do not assemble or link.
gcc –S filename.i -o filename.s
也是可行的。但是我遇到头文件冲突的问题error: declaration for parameter ‘__u_char’ but no such parameter
cc –S filename.cpp -o filename.s
cc1
命令-O3
)如果想把 C 语言变量的名称作为汇编语言语句中的注释,可以加上 -fverbose-asm
选项:
请阅读 GNU assembly file一文
汇编器:将.s 文件转化成 .o文件,
gcc –c
,-c Compile and assemble, but do not link.
as
;目标文件由段组成。通常一个目标文件中至少有两个段:
代码段:该段中所包含的主要是程序的指令。该段一般是可读和可执行的,但一般却不可写。
objdump -Sd ../build/bin/pivot > pivot1.s
-S
以汇编代码的形式显示C++原程序代码,如果有debug信息,会显示源代码。nm file.o
查看目标文件中的符号表注意,这时候的目标文件里的使用的函数可能没定义,需要链接其他目标文件.a .so .o .dll
(Dynamic Link Library的缩写,Windows动态链接库)
List symbol names in object files.
no symbols
常用选项 -CD
-C
选项告诉 nm 将 C++ 符号的 mangled 名称转换为原始的、易于理解的名称。-D
/ --dynamic:显示动态符号,这在查看共享库(如 .so 文件)时非常有用。输出
符号类型 | 描述 |
---|---|
A | 符号值是绝对的。在进一步的连接中,不会被改变。 |
B | 符号位于未初始化数据段(known as BSS). |
C | 共用(common)符号. 共用符号是未初始化的数据。在连接时,多个共用符号可能采用一个同样的名字,如果这个符号在某个地方被定义,共用符号被认为是未定义的引用. |
D | 已初始化数据段的符号 |
G | 已初始化数据段中的小目标(small objective)符号. 一些目标文件格式允许更有效的访问小目标数据,比如一个全局的int变量相对于一个大的全局数组。 |
I | 其他符号的直接应用,这是GNU扩展的,很少用了. N 调试符号. |
R | 只读数据段符号. S 未初始化数据段中的小目标(small object)符号. |
T | 代码段的符号. |
U | 未定义符号. |
V | 弱对象(weak object)符号. 当一个已定义的弱符号被连接到一个普通定义符号,普通定义符号可以正常使用,当一个未定义的弱对象被连接到一个未定义的符号,弱符号的值为0. |
W | 一个没有被指定一个弱对象符号的弱符号(weak symbol)。 - a.out目标文件中的刺符号(stabs symbol). 这种情况下,打印的下一个值是其他字段,描述字段,和类型。刺符号用于保留调试信息. |
? | 未知符号类型,或者目标文件特有的符号类型. |
ldconfig 命令用于配置动态链接器的运行时绑定。你可以使用它来查询系统上已知的库文件的位置。
查询 libdw.so 的位置:
ldd
会显示动态库的链接关系,中间的nm
为U
没关系,只需要最终.so
对应符号是T
即可。
通过使用ld
命令,将编译好的目标文件连接成一个可执行文件或动态库。
Foo::bar(int,long)
会变成bar__3Fooil
。其中3是名字字符数见 Linux Executable file: Structure & Running
undefined reference to
一旦链接器完成了符号解析这一步,就把代码中的每个符号引用和正好一个符号定义(即它的一个输入目标模块中的一个符号表条目)关联起来。此时,链接器就知道它的输入目标模块中的代码节和数据节的确切大小。现在就可以开始重定位步骤了,在这个步骤中,将合并输入模块,并为每个符号分配运行时地址。重定位由两步组成:
.data
节被全部合并成一个节,这个节成为输出的可执行目标文件的.data
节。当汇编器生成一个目标模块时,它并不知道数据和代码最终将放在内存中的什么位置。它也不知道这个模块引用的任何外部定义的函数或者全局变量的位置。所以,无论何时汇编器遇到对最终位置未知的目标引用,它就会生成一个重定位条目,告诉链接器在将目标文件合并成可执行文件时如何修改这个引用。
代码的重定位条目放在 .rel.text
中。已初始化数据的重定位条目放在 .rel.data
中。
下面 展示了 ELF 重定位条目的格式。
R_X86_64_PC32
。重定位一个使用 32 位 PC 相对地址的引用。回想一下 3.6.3 节,一个 PC 相对地址就是距程序计数器(PC)的当前运行时值的偏移量。当 CPU 执行一条使用 PC 相对寻址的指令时,它就将在指令中编码的 32 位值加上 PC 的当前运行时值,得到有效地址(如 call 指令的目标),PC 值通常是下一条指令在内存中的地址。(将 PC 压入栈中来使用)R_X86_64_32
。重定位一个使用 32 位绝对地址的引用。通过绝对寻址,CPU 直接使用在指令中编码的 32 位值作为有效地址,不需要进一步修改。typedef struct {
long offset; /* Offset of the reference to relocate */
long type:32, /* Relocation type */
symbol:32; /* Symbol table index */
long addend; /* Constant part of relocation expression */
} Elf64_Rela;
链接器通常从左到右解析依赖项,这意味着如果库 A 依赖于库 B,那么库 B 应该在库 A 之前被链接。
库顺序
假设有三个库 libA, libB, 和 libC,其中 libA 依赖 libB,而 libB 又依赖 libC。在 CMake 中,你应该这样链接它们:
这样的顺序确保了当链接器处理 libA 时,libB 和 libC 中的符号已经可用。
静态库static library就是将相关的目标模块打包形成的单独的文件。使用ar命令。
静态库的优点在于:
问题:
深入理解计算机系统P477,静态库例子
图 7-8 概括了链接器的行为。-static
参数告诉编译器驱动程序,链接器应该构建一个完全链接的可执行目标文件,它可以加载到内存并运行,在加载时无须更进一步的链接。-lvector
参数是 libvector.a
的缩写,-L. 参数告诉链接器在当前目录下查找 libvector.a。
共享库是以两种不同的方式来“共享”的:
如上创建了一个可执行目标文件 prog2l,而此文件的形式使得它在运行时可以和 libvector.so 链接。基本的思路是:
dlopen()
interface.情况:在应用程序被加载后执行前时,动态链接器加载和链接共享库的情景。
核心思想:由动态链接器接管,加载管理和关闭共享库(比如,如果没有其他共享库还在使用这个共享库,dlclose函数就卸载该共享库。)。
.interp
节,这一节包含动态链接器的路径名,动态链接器本身就是一个共享目标(如在 Linux 系统上的 ld-linux.so). 加载器不会像它通常所做地那样将控制传递给应用,而是加载和运行这个动态链接器。然后,动态链接器通过执行下面的重定位完成链接任务:最后,动态链接器将控制传递给应用程序。从这个时刻开始,共享库的位置就固定了,并且在程序执行的过程中都不会改变。
情况:应用程序在运行时要求动态链接器加载和链接某个共享库,而无需在编译时将那些库链接到应用。
实际应用情况:
思路是将每个生成动态内容的函数打包在共享库中。
编译器yasm
的参数-DPIE
如果同一份代码可能被加载到进程空间的任意虚拟地址上执行(如共享库和动态加载代码),那么就需要使用-fPIC生成位置无关代码。
可以加载而无需重定位的代码称为位置无关代码(Position-Independent Code,PIC)
在一个 x86-64 系统中,对同一个目标模块中符号的引用是不需要特殊处理使之成为 PIC。可以用 PC 相对寻址来编译这些引用,构造目标文件时由静态链接器重定位。
解决方法:延迟绑定(lazy binding),将过程地址的绑定推迟到第一次调用该过程时。
动机:使用延迟绑定的动机是对于一个像 libc.so 这样的共享库输出的成百上千个函数中,一个典型的应用程序只会使用其中很少的一部分。把函数地址的解析推迟到它实际被调用的地方,能避免动态链接器在加载时进行成百上千个其实并不需要的重定位。
结果:第一次调用过程的运行时开销很大,但是其后的每次调用都只会花费一条指令和一个间接的内存引用。
实现:延迟绑定是通过两个数据结构之间简洁但又有些复杂的交互来实现的,这两个数据结构是:GOT 和过程链接表(Procedure Linkage Table,PLT)。如果一个目标模块调用定义在共享库中的任何函数,那么它就有自己的 GOT 和 PLT。GOT 是数据段的一部分,而 PLT 是代码段的一部分。
首先,让我们介绍这两个表的内容。
PLT[0]
是一个特殊条目,它跳转到动态链接器中。PLT[1]
(图中未显示)调用系统启动函数(__libc_start_main
),它初始化执行环境,调用 main 函数并处理其返回值从 PLT[2] 开始的条目调用用户代码调用的函数。在我们的例子中,PLT[2] 调用 addvec,PLT[3](图中未显示)调用 printf。上图a 展示了 GOT 和 PLT 如何协同工作,在 addvec 被第一次调用时,延迟解析它的运行时地址:
上图b 给出的是后续再调用 addvec 时的控制流:
静态库
动态库
shaojiemike@snode6 /lib/modules/5.4.0-107-generic/build [06:32:26]
> gcc -print-search-dirs
install: /usr/lib/gcc/x86_64-linux-gnu/9/
programs: =/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/bin/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/bin/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/bin/
libraries: =/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/lib/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/lib/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/9/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/9/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/
加载器:将可执行程序加载到内存并进行执行,loader和ld-linux.so。
将可执行文件加载运行
命令 | 描述 |
---|---|
ar | 创建静态库,插入、删除、列出和提取成员; |
stringd | 列出目标文件中所有可以打印的字符串; |
strip | 从目标文件中删除符号表信息; |
nm | 列出目标文件符号表中定义的符号; |
size | 列出目标文件中节的名字和大小; |
readelf | 显示一个目标文件的完整结构,包括ELF 头中编码的所有信息。 |
objdump | 显示目标文件的所有信息,最有用的功能是反汇编.text节中的二进制指令。 |
ldd | 列出可执行文件在运行时需要的共享库。 |
ltrace 跟踪进程调用库函数过程 strace 系统调用的追踪或信号产生的情况 Relyze 图形化收费试用
-g
选项,可以生成调试信息,这样在gdb中可以查看源代码。objdump -g <archive_file>.a
# 如果.o文件有debugging symbols,会输出各section详细信息
Contents of the .debug_aranges section (loaded from predict-c.o):
# 没有则如下
cabac-a.o: file format elf64-x86-64
dct-a.o: file format elf64-x86-64
deblock-a.o: file format elf64-x86-64
gcc -E -g testBigExe.cpp -o testDebug.i
相对于无-g
的命令,只会多一行信息# 1 "/staff/shaojiemike/test/OS//"
gcc -S -g testBigExe.cpp -o testDebug.s
,对比之前的汇编文件,由72行变成9760行。具体解析参考 GNU assembly file一文简单的#pragma omp for
,编译后多出汇编代码如下。当前可以创建多少个线程默认汇编并没有显示的汇编指令。
call omp_get_num_threads@PLT
movl %eax, %ebx
call omp_get_thread_num@PLT
movl %eax, %ecx
call GOMP_barrier@PLT
某些atomic的导语会变成对应汇编
暂无
基础不牢,地动山摇。ya 了。
https://www.cnblogs.com/LiuYanYGZ/p/5574601.html
https://hansimov.gitbook.io/csapp/part2/ch07-linking/7.5-symbols-and-symbol-tables
TODO:[5] please fix all in free time
版本冲突的几个主要原因:
STL
__THROW
) in it's header files, part sys header(e.g, iostream
) is included by old project, but the definition of new func is not included for lower search priority.xxx
in header search pathcompile multipim with pin3.28 under g++11
/usr/include/x86_64-linux-gnu/c++/11/bits/os_defines.h:44:19: error: missing binary operator before token "("
4| #if __GLIBC_PREREQ(2,15) && defined(_GNU_SOURCE)
Gabriel Devillers
answer the key point, self head file's higher priority lead to the no define of __GLIBC_PREREQ()
PIN/extras/crt/include/features.h
feature_bk.h
In file included from pin/extras/crt/include/sys/cdefs.h:84,
from pin/extras/crt/include/features.h:33,
from pin/extras/cxx/include/__config:228,
from pin/extras/cxx/include/string:510,
from build/opt/g_std/g_string.h:31,
from build/opt/access_tracing.h:29,
from build/opt/access_tracing.cpp:26:
/usr/include/x86_64-linux-gnu/sys/cdefs.h:146:55: error: missing binary operator before token "("
146 | #if __USE_FORTIFY_LEVEL == 3 && (__glibc_clang_prereq (9, 0) \
| ^
We find the definition
# shaojiemike @ icarus0 in ~/github/MultiPIM_icarus0 on git:main x [16:45:13] C:2
$ ag -us "__glibc_clang_prereq" /usr/include ./pin ./common ./build/opt /usr/lib/gcc/x86_64-linux-gnu/11/include /usr/local/include
/usr/include/features.h
179:# define __glibc_clang_prereq(maj, min) \
182:# define __glibc_clang_prereq(maj, min) 0
413:# elif _FORTIFY_SOURCE > 2 && (__glibc_clang_prereq (9, 0) \
TODO: maybe include_next
in pin/extras/crt/include/features.h
during the officail pintool compilation of pin2.14 under g++11
#if !defined(__GXX_ABI_VERSION) || CC_USED_ABI_VERSION != __GXX_ABI_VERSION
#error The C++ ABI of your compiler does not match the ABI of the pin kit.
#endif
TODO:
compile multipim with pin3.28 under g++11 after adding crt include path.
In file included from /usr/include/c++/11/bits/localefwd.h:40,
from /usr/include/c++/11/string:43,
from build/opt/g_std/g_string.h:31,
from build/opt/access_tracing.h:29,
from build/opt/access_tracing.cpp:26:
/usr/include/x86_64-linux-gnu/c++/11/bits/c++locale.h: In function 'int std::__convert_from_v(const __c_locale&, char*, int, const char*, ...)':
/usr/include/x86_64-linux-gnu/c++/11/bits/c++locale.h:75:16: error: variable 'std::__c_locale __old' has initializer but incomplete type
75 | __c_locale __old = __gnu_cxx::__uselocale(__cloc);
| ^~~~~
/usr/include/x86_64-linux-gnu/c++/11/bits/c++locale.h:75:47: error: cannot convert 'const __c_locale' to 'locale_t' {aka '__locale_t*'}
75 | __c_locale __old = __gnu_cxx::__uselocale(__cloc);
| ^~~~~~
| |
| const __c_locale
/usr/include/x86_64-linux-gnu/c++/11/bits/c++locale.h:52:34: note: initializing argument 1 of '__locale_t* __gnu_cxx::__uselocale(locale_t)'
52 | extern "C" __typeof(uselocale) __uselocale;
| ^~~~~~~~~~~
error: initializer but incomplete type is caused by compiler-think undefined type.
But the define is just before lines typedef __locale_t __c_locale;
And found the conflict defined
# shaojiemike @ icarus0 in ~/github/MultiPIM_icarus0/pin on git:main x [9:56:26]
$ ag __locale_t
extras/crt/include/xlocale.h
33:struct __locale_t;
34:typedef struct __locale_t* locale_t;
replace these two lines to std header file
struct __locale_struct
{
/* Note: LC_ALL is not a valid index into this array. */
struct __locale_data *__locales[13]; /* 13 = __LC_LAST. */
/* To increase the speed of this solution we add some special members. */
const unsigned short int *__ctype_b;
const int *__ctype_tolower;
const int *__ctype_toupper;
/* Note: LC_ALL is not a valid index into this array. */
const char *__names[13];
};
typedef struct __locale_struct *__locale_t;
typedef __locale_t locale_t;
In file included from /usr/include/c++/11/cstdlib:75,
from /usr/include/c++/11/ext/string_conversions.h:41,
from /usr/include/c++/11/bits/basic_string.h:6608,
from /usr/include/c++/11/string:55,
from build/opt/g_std/g_string.h:31,
from build/opt/access_tracing.h:29,
from build/opt/access_tracing.cpp:26:
/usr/include/stdlib.h:97: note: this is the location of the previous definition
97 | #define MB_CUR_MAX (__ctype_get_mb_cur_max ())
|
/usr/include/stdlib.h:98:45: error: expected initializer before '__THROW'
98 | extern size_t __ctype_get_mb_cur_max (void) __THROW __wur;
| ^~~~~~~
This shows error of the definition the __THROW
. Ensure that the __THROW
macro is correctly defined or included in your code.
$ ag -us "def.*__THROW" /usr/include ./pin ./common ./build/opt /usr/lib/gcc/x86_64-linux-gnu/11/include /usr/local/include
/usr/include/x86_64-linux-gnu/sys/cdefs.h
79:# define __THROW __attribute__ ((__nothrow__ __LEAF))
80:# define __THROWNL __attribute__ ((__nothrow__))
86:# define __THROW noexcept (true)
88:# define __THROW throw ()
So __THROW
is defined in /usr/include/x86_64-linux-gnu/sys/cdefs.h
Stupid idea is to sudo vim the sys-header stdlib.h
add codes:
In file included from build/opt/pin_cmd.cpp:30:
/usr/include/wordexp.h:66:45: error: expected initializer before '__THROW'
66 | extern void wordfree (wordexp_t *__wordexp) __THROW;
| ^~~~~~~
# wordexp.h -> <features.h> -> sys/cdefs.h
The more likely scenario is pin-def cdefs.h
lack the definition of macro __THROW
$ ag -usg "cdefs\.h" /usr/include ./pin ./common ./build/opt /usr/lib/gcc/x86_64-linux-gnu/11/include /usr/local/include
/usr/include/bsd/sys/cdefs.h
/usr/include/x86_64-linux-gnu/sys/cdefs.h
pin/extras/crt/include/sys/cdefs.h
It's a bad idea to include_next
which lead to 7.1
error.
The easy solution is to degrade the wordexp.h
with remove the only one macro __THROW
.
In file included from pin/source/include/pin/pin.H:27,
from build/opt/decoder.h:31,
from build/opt/core.h:30,
from build/opt/ooo_core.h:34,
from build/opt/contention_sim.cpp:35:
pin/extras/components/include/util/intel-fp.hpp: At global scope:
pin/extras/components/include/util/intel-fp.hpp:21:9: error: 'UINT64' does not name a type; did you mean 'UINT64_C'?
21 | UINT64 _significand; ///< The floating-point significand.
| ^~~~~~
| UINT64_C
Type is not defined, include to fix
# shaojiemike @ icarus0 in ~/github/MultiPIM_icarus0 on git:main x [16:16:38]
$ ag ' UINT64;'
pin/extras/crt/include/types.h
70:typedef unsigned __int64 UINT64;
86:typedef uint64_t UINT64;
In file included from build/opt/debug_zsim.cpp:28:
/usr/include/gelf.h:70:9: error: 'Elf64_Section' does not name a type; did you mean 'Elf64_Ssize'?
70 | typedef Elf64_Section GElf_Section;
| ^~~~~~~~~~~~~
| Elf64_Ssize
We found the definition
# shaojiemike @ icarus0 in ~/github/MultiPIM_icarus0 on git:main x [15:57:57] C:2
$ ag -us "Elf64_Section" /usr/include ./pin ./common ./build/opt /usr/lib/gcc/x86_64-linux-gnu/11/include /usr/local/include
/usr/include/gelf.h
70:typedef Elf64_Section GElf_Section;
/usr/include/elf.h
52:typedef uint16_t Elf64_Section;
532: Elf64_Section st_shndx; /* Section index */
the reason is header higher search priority
$ ag -usg "elf.h" /usr/include ./pin ./common ./build/opt /usr/lib/gcc/x86_64-linux-gnu/11/include /usr/local/include
/usr/include/gelf.h
/usr/include/elf.h
pin/extras/crt/include/elf.h
pin/extras/crt/include/freebsd/3rd-party/sys/x86/include/elf.h # used by pin/extras/crt/include/elf.h
We can not just add #include_next
in pin's elf.h
due the redefined of many structs.
We fix it by add missing macro definitions in suitable header file pin/extras/crt/include/freebsd/3rd-party/include/elf.h
/* Type for section indices, which are 16-bit quantities. */
typedef uint16_t Elf32_Section;
typedef uint16_t Elf64_Section;
In file included from pin/source/include/pin/pin.H:96,
from build/opt/decoder.h:32,
from build/opt/decoder.cpp:26:
pin/source/include/pin/gen/ins_api_xed_ia32.PH:65:27: error: reference to 'USIZE' is ambiguous
65 | extern PIN_DEPRECATED_API USIZE INS_MemoryWriteSize(INS ins);
| ^~~~~
conflict define in current path header and search path header, select one to comment.
# shaojiemike @ icarus0 in ~/github/MultiPIM_icarus0 on git:main x [16:39:02]
$ ag ' USIZE;' pin
pin/extras/crt/include/types.h
122:typedef ADDRINT USIZE;
pin/source/include/pin/gen/types_foundation.PH
41:typedef unsigned int USIZE;
In file included from build/opt/slab_alloc.h:43,
from build/opt/event_recorder.h:32,
from build/opt/cache.cpp:29:
build/opt/mutex.h: At global scope:
build/opt/mutex.h:56:30: error: reference to 'mutex' is ambiguous
56 | class aligned_mutex : public mutex {} ATTR_LINE_ALIGNED;
| ^~~~~
In file included from pin/extras/cxx/include/mutex:190,
from pin/extras/cxx/include/__locale:18,
from pin/extras/cxx/include/ios:215,
from pin/extras/cxx/include/iostream:37,
from build/opt/memory_hierarchy.h:32,
from build/opt/cache_arrays.h:29,
from build/opt/cache.h:29,
from build/opt/cache.cpp:26:
pin/extras/cxx/include/__mutex_base:32:78: note: candidates are: 'class std::__1::mutex'
32 | class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex
| ^~~~~
In file included from build/opt/slab_alloc.h:43,
from build/opt/event_recorder.h:32,
from build/opt/cache.cpp:29:
build/opt/mutex.h:34:7: note: 'class mutex'
34 | class mutex : public GlobAlloc {
| ^~~~~
It seems the class redefine, we comment pintool part code to fix it.
In file included from pin/extras/cxx/include/mutex:190,
from pin/extras/cxx/include/__locale:18,
from pin/extras/cxx/include/ios:215,
from pin/extras/cxx/include/iostream:37,
from build/opt/memory_hierarchy.h:32,
from build/opt/access_tracing.h:30,
from build/opt/access_tracing.cpp:26:
pin/extras/cxx/include/__mutex_base: In member function 'void std::__1::condition_variable::__do_timed_wait(std::__1::unique_lock<std::__1::mutex>&, std::__1::chrono::time_point<std::__1::chrono::steady_clock, std::__1::chrono::duration<long long int, std::__1::ratio<1, 1000000000> > >)':
pin/extras/cxx/include/__mutex_base:508:16: error: 'pthread_cond_clockwait' was not declared in this scope; did you mean 'pthread_cond_wait'?
508 | int __ec = pthread_cond_clockwait(&__cv_, __lk.mutex()->native_handle(), CLOCK_MONOTONIC, &__ts);
| ^~~~~~~~~~~~~~~~~~~~~~
| pthread_cond_wait
After Reading header file, It seem compiler believe system contain the function.
TODO: 阅读system header file 的include和底层代码实现: 线程,print,syscall。e.g., pthread_cond_clockwait
function is defined where
# shaojiemike @ icarus0 in ~/github/MultiPIM_icarus0 on git:main x [15:10:32]
$ ag pthread_cond_clockwait /usr/include
/usr/include/pthread.h
1171:extern int pthread_cond_clockwait (pthread_cond_t *__restrict __cond,
Of course,We assume pin/extras/crt/include/pthread.h
has higher include priority. We will prove it in the later.
# the exsit include
$ ag pthread.h pin/extras/cxx
pin/extras/cxx/include/__threading_support
32:# include <pthread.h>
# So who include __threading_support
$ ag __threading_support pin/extras/cxx
pin/extras/cxx/include/__mutex_base # the error header
16:#include <__threading_support>
Reading __threading_support
code, the include under a #ifdef
condition
#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
# include <pthread.h>
...
#elif defined(_LIBCPP_HAS_THREAD_API_C11)
# include <threads.h>
#endif
So which file define _LIBCPP_HAS_THREAD_API_PTHREAD
$ ag -u _LIBCPP_HAS_THREAD_API_PTHREAD
pin/extras/cxx/include/__config
1134: !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && \
1149:# define _LIBCPP_HAS_THREAD_API_PTHREAD
1152:# define _LIBCPP_HAS_THREAD_API_PTHREAD
1160:#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
1170:#if defined(_LIBCPP_HAS_NO_THREADS) && defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
1171:#error _LIBCPP_HAS_THREAD_API_PTHREAD may only be defined when \
1199:#if (defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && defined(__GLIBC__)) \
# second one define it
# and find #include <__config> in the error header
According to -MMD
option's result .d
file, we make sure include the pin/extras/cxx/include/__config
one.
And add #warning
preprocessor directive or check -MD
option result to make sure include <pthread.h>
. But the point is include pin/extras/crt/include/pthread.h
First Idea: I believe that changing the potentially buggy Pin crt
code is a bad idea. The more likely scenario is that we are using the crt
incorrectly. So, let's identify how to trigger the bug starting from build/opt/memory_hierarchy.h:32
, and then replicate it in a simple pintool to verify whether we are indeed using it incorrectly.
But the real situation is pintool just #include <iostream>
and the simple pintool also include without compilation error. Weird scenario deserves more research.
# pass
# shaojiemike @ icarus0 in ~/github/MultiPIM_icarus0/pin/source/tools/ManualExamples on git:main x [10:02:19]
$ g++ -Wall -Werror -Wno-unknown-pragmas -DPIN_CRT=1 -fno-stack-protector -DTARGET_IA32E -DHOST_IA32E -fPIC -DTARGET_LINUX -fabi-version=2 -I../../../sou
rce/include/pin -I../../../source/include/pin/gen -isystem /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/cxx/include -isystem /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/crt/include -isystem /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/crt/include/arch-x86_64 -isystem /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/crt/include/kernel/uapi -isystem /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/crt/include/kernel/uapi/asm-x86 -I../../../extras/components/include -I../../../extras/xed-int
el64/include/xed -I../../../source/tools/Utils -I../../../source/tools/InstLib -O3 -fomit-frame-pointer -MD -c inscount0.cpp
# failed
# shaojiemike @ icarus0 in ~/github/MultiPIM_icarus0/pin/source/tools/ManualExamples on git:main x [10:02:53]
$ g++ -Wall -Werror -Wno-unknown-pragmas -DPIN_CRT=1 -fno-stack-protector -DTARGET_IA32E -DHOST_IA32E -fPIC -DTARGET_LINUX -fabi-version=2 -I../../../sou
rce/include/pin -I../../../source/include/pin/gen -isystem /staff/shaojiemike/github/MultiPIM_icarus0/pin/extras/cxx/include -isystem /staff/shaojiemike/github/MultiPIM_icarus0/pin/extras/crt/include -isystem /staff/shaojiemike/github/MultiPIM_icarus0/pin/extras/crt/include/arch-x86_64 -isystem /staff/shaojiemike/github/MultiPIM_icarus0/pin/extras/crt/include/kernel/uapi -isystem /staff/shaojiemike/github/MultiPIM_icarus0/pin/extras/crt/include/kernel/uapi/asm-x86 -I../../../extras/components/include -I../../../extras/xed-intel64/include/xed -I../../../source/tools/Utils -I../../../source/tools/InstLib -O3 -fomit-frame-pointer -MD -c inscount0.cpp
In file included from /staff/shaojiemike/github/MultiPIM_icarus0/pin/extras/cxx/include/mutex:190,
from /staff/shaojiemike/github/MultiPIM_icarus0/pin/extras/cxx/include/__locale:18,
from /staff/shaojiemike/github/MultiPIM_icarus0/pin/extras/cxx/include/ios:215,
from /staff/shaojiemike/github/MultiPIM_icarus0/pin/extras/cxx/include/iostream:37,
from inscount0.cpp:6:
/staff/shaojiemike/github/MultiPIM_icarus0/pin/extras/cxx/include/__mutex_base: In member function 'void std::__1::condition_variable::__do_timed_wait(std::__1::unique_lock<std::__1::mutex>&, std::__1::chrono::time_point<std::__1::chrono::steady_clock, std::__1::chrono::duration<long long int, std::__1::ratio<1, 1000000000> > >)':
/staff/shaojiemike/github/MultiPIM_icarus0/pin/extras/cxx/include/__mutex_base:508:16: error: 'pthread_cond_clockwait' was not declared in this scope; did you mean 'pthread_cond_wait'?
508 | int __ec = pthread_cond_clockwait(&__cv_, __lk.mutex()->native_handle(), CLOCK_MONOTONIC, &__ts);
| ^~~~~~~~~~~~~~~~~~~~~~
| pthread_cond_wait
After the compile compare, we decide the error is due to our change in pin code.
But we just change a little.
# shaojiemike @ icarus0 in ~/github/MultiPIM_icarus0 on git:main x [10:09:58]
$ diff /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux pin
diff '--color=auto' -r /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/crt/include/features.h pin/extras/crt/include/features.h
32a33
> #include_next <features.h>
diff '--color=auto' -r /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/crt/include/freebsd/3rd-party/include/elf.h pin/extras/crt/include/freebsd/3rd-party/include/elf.h
42a43,46
> /* Type for section indices, which are 16-bit quantities. */
> typedef uint16_t Elf32_Section;
> typedef uint16_t Elf64_Section;
>
diff '--color=auto' -r /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/crt/include/sys/cdefs.h pin/extras/crt/include/sys/cdefs.h
44a45
>
82a84,114
> #include_next <sys/cdefs.h>
>
>
> /* GCC can always grok prototypes. For C++ programs we add throw()
> to help it optimize the function calls. But this only works with
> gcc 2.8.x and egcs. For gcc 3.4 and up we even mark C functions
> as non-throwing using a function attribute since programs can use
> the -fexceptions options for C code as well. */
> // # if !defined __cplusplus \
> // && (__GNUC_PREREQ (3, 4) || __glibc_has_attribute (__nothrow__))
> // # define __THROW __attribute__ ((__nothrow__ __LEAF))
> // # define __THROWNL __attribute__ ((__nothrow__))
> // # define __NTH(fct) __attribute__ ((__nothrow__ __LEAF)) fct
> // # define __NTHNL(fct) __attribute__ ((__nothrow__)) fct
> // # else
> // # if defined __cplusplus && (__GNUC_PREREQ (2,8) || __clang_major >= 4)
> // # if __cplusplus >= 201103L
> // # define __THROW noexcept (true)
> // # else
> // # define __THROW throw ()
> // # endif
> // # define __THROWNL __THROW
> // # define __NTH(fct) __LEAF_ATTR fct __THROW
> // # define __NTHNL(fct) fct __THROW
> // # else
> // # define __THROW
> // # define __THROWNL
> // # define __NTH(fct) fct
> // # define __NTHNL(fct) fct
> // # endif
> // # endif
Rollback two include_next to pass the benchmark.
In file included from pin/extras/cxx/include/limits.h:57,
from pin/extras/cxx/include/climits:41,
from pin/extras/cxx/include/ratio:82,
from pin/extras/cxx/include/chrono:830,
from pin/extras/cxx/include/__threading_support:15,
from pin/extras/cxx/include/atomic:579,
from pin/extras/cxx/include/memory:687,
from pin/extras/cxx/include/algorithm:653,
from pin/extras/cxx/include/__string:57,
from pin/extras/cxx/include/string_view:179,
from pin/extras/cxx/include/string:511,
from build/opt/g_std/g_string.h:31,
from build/opt/access_tracing.h:29,
from build/opt/access_tracing.cpp:26:
build/opt/common/global_const.h:32:16: error: expected unqualified-id before numeric constant
32 | const unsigned PAGE_SIZE=(1UL<<PAGE_SHIFT);
| ^~~~~~~~~
Ref suggest us to test the macro define
In file included from build/opt/common/common_structures.h:20,
from build/opt/memory_hierarchy.h:39,
from build/opt/access_tracing.h:30,
from build/opt/access_tracing.cpp:26:
build/opt/common/global_const.h:33:2: error: #error "PAGE_SIZE is defined"
33 | #error "PAGE_SIZE is defined"
| ^~~~~
and we find the redefined in
# shaojiemike @ icarus0 in ~/github/MultiPIM_icarus0 on git:main x [10:28:46]
$ ag -u "define PAGE_SIZE"
pin/extras/crt/include/limits.h
124:#define PAGE_SIZE 4096
pin/extras/crt/include/kernel/uapi/linux/a.out.h
120:#define PAGE_SIZE 0x400
FIX: set #ifdef
in old pintool code.
During the zsim-like multipim compilation, dumptrace
g++ -o build/opt/dumptrace -Wl,-R/staff/shaojiemike/github/MultiPIM_icarus0/common/libconfig/lib -L/usr/lib/x86_64-linux-gnu/hdf5/serial/ build/opt/dumptrace.ot build/opt/access_tracing.ot build/opt/memory_hierarchy.ot build/opt/config.ot build/opt/galloc.ot build/opt/log.ot build/opt/pin_cmd.ot -Lcommon/libconfig/lib -lconfig++ -lhdf5 -lhdf5_hl
/usr/bin/ld: build/opt/dumptrace.ot: in function `std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::basic_string<decltype(nullptr)>(char const*)':
/staff/shaojiemike/github/MultiPIM_icarus0/pin/extras/cxx/include/string:841: undefined reference to `std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__init(char const*, unsigned long)'
After reading the code, template
function init
denifition seems no problem. So the first judgement is this is due to the new pin lib missing.
Copy all missing lib from inscount0.so
g++ -o build/opt/dumptrace -Wl,--hash-style=sysv /staff/shaojiemike/github/MultiPIM_icarus0/pin/intel64/runtime/pincrt/crtbeginS.o -Wl,-Bsymbolic -Wl,--version-script=/staff/shaojiemike/github/MultiPIM_icarus0/pin/source/include/pin/pintool.ver -fabi-version=2 -Wl,-R/staff/shaojiemike/github/MultiPIM_icarus0/common/libconfig/lib -L/staff/shaojiemike/github/MultiPIM_icarus0/pin/intel64/runtime/pincrt -L/staff/shaojiemike/github/MultiPIM_icarus0/pin/intel64/lib -L/staff/shaojiemike/github/MultiPIM_icarus0/pin/intel64/lib-ext -L/staff/shaojiemike/github/MultiPIM_icarus0/pin/extras/xed-intel64/lib -L/usr/lib/x86_64-linux-gnu/hdf5/serial/ build/opt/dumptrace.ot build/opt/access_tracing.ot build/opt/memory_hierarchy.ot build/opt/config.ot build/opt/galloc.ot build/opt/log.ot build/opt/pin_cmd.ot -Lcommon/libconfig/lib -lconfig++ -lhdf5 -lhdf5_hl -lpin -lxed /staff/shaojiemike/github/MultiPIM_icarus0/pin/intel64/runtime/pincrt/crtendS.o -lpindwarf -ldl-dynamic -nostdlib -lc++ -lc++abi -lm-dynamic -lc-dynamic -lunwind-dynamic
which lead error
/usr/bin/ld: build/opt/config.ot: undefined reference to symbol '__cxa_get_exception_ptr@@CXXABI_1.3.1'
/usr/bin/ld: /lib/x86_64-linux-gnu/libstdc++.so.6: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
forget add -shared
option to eliminate the error msg, but the I guess build/opt/dumptrace
is an excutable, because the code
int main(int argc, const char* argv[]) {
InitLog(""); //no log header
if (argc != 2) {
info("Prints an access trace");
info("Usage: %s <trace>", argv[0]);
exit(1);
}
...}
dumptrace
is executable and inscount0.so
is a dynamic library. We should analyse the lack part.
First we try to delete part and lower pin-lib priority
g++ -o build/opt/dumptrace -Wl,-R/staff/shaojiemike/github/MultiPIM_icarus0/common/libconfig/lib -L/usr/lib/x86_64-linux-gnu/hdf5/serial/ build/opt/dumptrace.ot build/opt/access_tracing.ot build/opt/memory_hierarchy.ot build/opt/config.ot build/opt/galloc.ot build/opt/log.ot build/opt/pin_cmd.ot -Lcommon/libconfig/lib -lconfig++ -lhdf5 -lhdf5_hl -L/staff/shaojiemike/github/MultiPIM_icarus0/pin/intel64/runtime/pincrt -L/staff/shaojiemike/github/MultiPIM_icarus0/pin/intel64/lib -L/staff/shaojiemike/github/MultiPIM_icarus0/pin/intel64/lib-ext -L/staff/shaojiemike/github/MultiPIM_icarus0/pin/extras/xed-intel64/lib -lpin -lxed -lpindwarf -ldl-dynamic -nostdlib -lc++ -lc++abi -lm-dynamic -lc-dynamic -lunwind-dynamic
which alse error with __cxa_get_exception_ptr@@CXXABI_1.3.1
and error adding symbols: DSO missing from command line
TODO: ???
/usr/bin/ld: build/opt/dumptrace.ot: in function `AccessTraceReader::read()':
/staff/shaojiemike/github/MultiPIM_icarus0/build/opt/access_tracing.h:70: undefined reference to `__assert2'
暂无
暂无
上面回答部分来自ChatGPT-3.5,没有进行正确性的交叉校验。
无
常见的问题:
主要原因是头文件的include的使用不同,还有一些接口的改变。
$ make obj-intel64/inscount0.so
g++
# Warning Options
-Wall -Werror -Wno-unknown-pragmas -Wno-dangling-pointer
# Program Instrumentation Options
-fno-stack-protector
# Code-Gen-Options
-fno-exceptions -funwind-tables -fasynchronous-unwind-tables -fPIC
# C++ Dialect
-fabi-version=2 -faligned-new -fno-rtti
# define
-DPIN_CRT=1 -DTARGET_IA32E -DHOST_IA32E -DTARGET_LINUX
# include
-I../../../source/include/pin
-I../../../source/include/pin/gen
-isystem /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/cxx/include
-isystem /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/crt/include
-isystem /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/crt/include/arch-x86_64
-isystem /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/crt/include/kernel/uapi
-isystem /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/crt/include/kernel/uapi/asm-x86
-I../../../extras/components/include
-I../../../extras/xed-intel64/include/xed
-I../../../source/tools/Utils
-I../../../source/tools/InstLib
# Optimization Options
-O3 -fomit-frame-pointer -fno-strict-aliasing
-c -o obj-intel64/inscount0.o inscount0.cpp
g++ -shared -Wl,--hash-style=sysv ../../../intel64/runtime/pincrt/crtbeginS.o -Wl,-Bsymbolic -Wl,--version-script=../../../source/include/pin/pintool.ver -fabi-version=2
-o obj-intel64/inscount0.so obj-intel64/inscount0.o
-L../../../intel64/runtime/pincrt
-L../../../intel64/lib
-L../../../intel64/lib-ext
-L../../../extras/xed-intel64/lib
-lpin -lxed ../../../intel64/runtime/pincrt/crtendS.o -lpindwarf -ldl-dynamic -nostdlib -lc++ -lc++abi -lm-dynamic -lc-dynamic -lunwind-dynamic
对应的makefile规则在source/tools/Config/makefile.default.rules
# Build the intermediate object file.
$(OBJDIR)%$(OBJ_SUFFIX): %.cpp
$(CXX) $(TOOL_CXXFLAGS) $(COMP_OBJ)$@ $<
# Build the tool as a dll (shared object).
$(OBJDIR)%$(PINTOOL_SUFFIX): $(OBJDIR)%$(OBJ_SUFFIX)
$(LINKER) $(TOOL_LDFLAGS) $(LINK_EXE)$@ $< $(TOOL_LPATHS) $(TOOL_LIBS)
UINT64
undefined bug: inscount0.cpp
include pin.H
which includes types_foundation.PH
由于old pintool 基于 pin2.14。作为对比也分析inscount0.so
的编译过程
g++
# Warning Options
-Wall -Werror -Wno-unknown-pragmas
# Program Instrumentation Options
-fno-stack-protector
# Code-Gen-Options
-fPIC
# define
-DBIGARRAY_MULTIPLIER=1 -DTARGET_IA32E -DHOST_IA32E -DTARGET_LINUX
-I../../../source/include/pin
-I../../../source/include/pin/gen
-I../../../extras/components/include
-I../../../extras/xed-intel64/include
-I../../../source/tools/InstLib
# Optimization Options
-O3 -fomit-frame-pointer -fno-strict-aliasing
-c -o obj-intel64/inscount0.o inscount0.cpp
同时multipim 的scons的编译细节如下,去除与pin无关的参数:
g++
# Warning Options
-Wall -Wno-unknown-pragmas
# c++ language
-std=c++0x
# Code-Gen-Options
-fPIC
# debug
-g
# Program Instrumentation Options
-fno-stack-protector
# Preprocessor Options ???TODO:
-MMD
# machine-dependent
-march=core2
# C++ Dialect
-D_GLIBCXX_USE_CXX11_ABI=0
-fabi-version=2
# define
-DBIGARRAY_MULTIPLIER=1 -DUSING_XED
-DTARGET_IA32E -DHOST_IA32E -DTARGET_LINUX
-DPIN_PATH="/staff/shaojiemike/github/MultiPIM_icarus0/pin/intel64/bin/pinbin" -DZSIM_PATH="/staff/shaojiemike/github/MultiPIM_icarus0/build/opt/libzsim.so" -DMT_SAFE_LOG
-Ipin/extras/xed-intel64/include
-Ipin/source/include/pin
-Ipin/source/include/pin/gen
-Ipin/extras/components/include
# Optimization Options
-O3 -funroll-loops -fomit-frame-pointer
-c -o build/opt/simple_core.os build/opt/simple_core.cpp
对比后,pin3.28 相对 pin2.14 编译时,
-DPIN_CRT=1
// pin/extras/crt/include/freebsd/3rd-party/include/elf.h
> typedef uint16_t Elf32_Section;
> typedef uint16_t Elf64_Section;
// /usr/include/wordexp.h
remove __THROW
First apply the two change to old pintool
暂无
暂无
上面回答部分来自ChatGPT-3.5,没有进行正确性的交叉校验。
无
#ifndef _LIBCPP_TYPE_VIS
# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS)
# define _LIBCPP_TYPE_VIS __attribute__ ((__visibility__("default")))
# else
# define _LIBCPP_TYPE_VIS
# endif
#endif
#ifndef _LIBCPP_THREAD_SAFETY_ANNOTATION
# ifdef _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS
# define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) __attribute__((x))
# else
# define _LIBCPP_THREAD_SAFETY_ANNOTATION(x)
# endif
#endif // _LIBCPP_THREAD_SAFETY_ANNOTATION
class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex
{
}
It's part of code from __mutex_base
暂无
暂无
上面回答部分来自ChatGPT-3.5,没有进行正确性的交叉校验。
无
-M
option is designed for auto-generate Makefile rules from g++ command.-E
option to STOP after preprocessor during the compilation-w
option to DISABLE/suppress all warnings.Using a complex g++ command as an example:
g++ -Wall -Werror -Wno-unknown-pragmas -DPIN_CRT=1 -fno-stack-protector -fno-exceptions -funwind-tables -fasynchronous-unwind-tables -fno-rtti -DTARGET_IA32E -DHOST_IA32E -fPIC -DTARGET_LINUX -fabi-version=2 -faligned-new -I../../../source/include/pin -I../../../source/include/pin/gen -isystem /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/cxx/include -isystem /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/crt/include -isystem /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/crt/include/arch-x86_64 -isystem /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/crt/include/kernel/uapi -isystem /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/crt/include/kernel/uapi/asm-x86 -I../../../extras/components/include -I../../../extras/xed-intel64/include/xed -I../../../source/tools/Utils -I../../../source/tools/InstLib -O3 -fomit-frame-pointer -fno-strict-aliasing -Wno-dangling-pointer
-M inscount0.cpp -o Makefile_bk
In Makefile_bk
inscount0.o: inscount0.cpp \
# sys header
/usr/include/stdc-predef.h \
/staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/cxx/include/iostream \
/usr/lib/gcc/x86_64-linux-gnu/11/include/float.h
# usr header
../../../source/include/pin/pin.H \
../../../extras/xed-intel64/include/xed/xed-interface.h \
... more header files
-MM
not include sys header file-MF filename
config the Makefile rules write to which file instead of to stdout.-M -MG
is designed to generate Makefile rules when there is header file missing, treated it as generated in normal.-M -MP
will generated M-rules for dependency between header filesheader1.h
includes header2.h
. So header1.h: header2.h
in Makefile-MD
== -M -MF file
without default option -E
file
has a suffix of .d
, e.g., inscount0.d
for -c inscount0.cpp
-MMD
== -MD
not include sys header file暂无
暂无
上面回答部分来自ChatGPT-3.5,没有进行正确性的交叉校验。
无
According to REF
“ library API + compiler ABI = library ABI ”
TODO:
We are talking about GNU G++ support
GCC 11.1.0 using libstdc++.so.6.0.29
icarus0 11.4.0 using previous version in documentlibstdc++.so
binary.libstdc++-v3/config/abi/pre/gnu.ver
in github code which shows the detail symbol in diff-verion.GCC 11.1.0: GLIBCXX_3.4.29, CXXABI_1.3.13
TODO: Is there a way to lower the abi verison during the compilation
The GNU C++ compiler, g++, has a compiler command line option to switch between various different C++ ABIs. This explicit version switch is the flag -fabi-version
. In addition, some g++ command line options may change the ABI as a side-effect of use. Such flags include -fpack-struct
and -fno-exceptions
, but include others: see the complete list in the GCC manual under the heading Options for Code Generation Conventions.
-fabi-version=n | Use version n of the C++ ABI. The default is version 0.(Version 2 is the version of the C++ ABI that first appeared in G++ 3.4, and was the default through G++ 4.9.) ABI: an application binary interface (ABI) is an interface between two binary program modules. Often, one of these modules is a library or operating system facility, and the other is a program that is being run by a user.
ldd -v /bin/ls
show many libc.so.6
in different GLIBC
version, chatGPT explain this due to maintain backward compatibility as much as possible to ensure that older programs continue to work on newer systems. This is achieved through versioned symbols and by providing multiple versions of shared libraries.
TODO: If i write a simple C program using DLL, what is the ldd -v
print out? will be a simgle verison of libc.so.6
? or the equal question is If /bin/ls
use diff api in diff versions of DDL.
TODO:
during the pintool compilation process
#if !defined(__GXX_ABI_VERSION) || CC_USED_ABI_VERSION != __GXX_ABI_VERSION
#error The C++ ABI of your compiler does not match the ABI of the pin kit.
#endif
TODO:
暂无
暂无
上面回答部分来自ChatGPT-3.5,没有进行正确性的交叉校验。
无
Pin 是一个动态二进制插桩工具:
Pin机制类似Just-In-Time (JIT) 编译器,Trace插桩的基本流程(以动态基本块BBLs为分析单位):
通过一个例子来说明动态基本块BBLs与 汇编代码的BB的区别
switch(i)
{
case 4: total++;
case 3: total++;
case 2: total++;
case 1: total++;
case 0:
default: break;
}
上述代码会编译成下面的汇编, 对于实际执行时跳转从.L7
进入的情况,BBLs包括四条指令,但是BB只会包括一条。
Pin会将cpuid, popf and REP prefixed 指令在执行break 成很多BBLs,导致执行的基本块比预想的要多。(主要原因是这些指令有隐式循环,所以Pin会将其拆分成多个BBLs)
kit
from Intel websiteThis part is always needed by pintool, for example Zsim, Sniper.
When you meet the following situation, you should consider update your pin version even you can ignore this warning by use flags like -ifeellucky
under high compatibility risk.
shaojiemike@snode6 ~/github/ramulator-pim/zsim-ramulator/pin [08:05:47]
> ./pin
E: 5.4 is not a supported linux release
because this will easily lead to the problem
PIN_Init
之前调用PIN_InitSymbols
。for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec))
{
for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn))
{
// Prepare for processing of RTN, an RTN is not broken up into BBLs,
// it is merely a sequence of INSs
RTN_Open(rtn);
for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins))
{
count++;
}
// to preserve space, release data associated with RTN after we have processed it
RTN_Close(rtn);
}
}
最重要的是
TRACE_AddInstrumentFunction
Add a function used to instrument at trace granularityINS_AddInstrumentFunction()
Add a function used to instrument at instruction granularityIMG_AddInstrumentFunction()
Use this to register a call back to catch the loading of an imageINS_InsertPredicatedCall()
// Forward pass over all instructions in bbl
for( INS ins= BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins) )
// Forward pass over all instructions in routine
for( INS ins= RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins) )
// Visit every basic block in the trace
for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl))
{
// Insert a call to docount before every bbl, passing the number of instructions
BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR)docount, IARG_UINT32, BBL_NumIns(bbl), IARG_END);
}
UINT32 memOperands = INS_MemoryOperandCount(ins);
// Iterate over each memory operand of the instruction.
for (UINT32 memOp = 0; memOp < memOperands; memOp++){
if (INS_MemoryOperandIsRead(ins, memOp)||INS_MemoryOperandIsWritten(ins, memOp)
//xxx
}
最重要的是
示例分析
// IPOINT_BEFORE 时运行的分析函数
VOID printip(VOID* ip) { fprintf(trace, "%p\n", ip); }
// Pin calls this function every time a new instruction is encountered
VOID InstructionFuc(INS ins, VOID* v)
{
// Insert a call to printip before every instruction, and pass it the IP
// IARG_INST_PTR:指令地址 一类的全局变量???
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)printip, IARG_INST_PTR, IARG_END);
}
int main(int argc, char* argv[])
{
// Initialize pin
if (PIN_Init(argc, argv)) return Usage();
// 登记InstructionFuc为以指令粒度插桩时每条指令触发的函数
INS_AddInstrumentFunction(InstructionFuc, 0);
// 登记PrintFuc为程序结束时触发的函数
PIN_AddFiniFunction(PrintFuc, 0);
// 部署好触发机制后开始运行程序
PIN_StartProgram();
return 0;
}
目标:以样例插桩工具的源码为对象,熟悉pin的debug流程。
以官方教程为例子:
uname -a #intel64
cd source/tools/ManualExamples
# source/tools/Config/makefile.config list all make option
make all OPT=-O0 DEBUG=1 TARGET=intel64 |tee make.log|my_hl
# or just select one: make obj-intel64/inscount0.so
# $(OBJDIR)%$(PINTOOL_SUFFIX) - Default rule for building tools.
# Example: make obj-intel64/mytool.so
测试运行
下面介绍Pin 提供的debug工具:
首先创建所需的-g
的stack-debugger.so
和应用fibonacci.exe
其中OPT=-O0
选项来自官方文档Using Fast Call Linkages
小节,说明需要OPT=-O0
选项来屏蔽makefile中的-fomit-frame-pointer
选项,使得GDB能正常显示stack trace(函数堆栈?)
$ ../../../pin -appdebug -t obj-intel64/stack-debugger.so -- obj-intel64/fibonacci.exe 1000
Application stopped until continued from debugger.
Start GDB, then issue this command at the prompt:
target remote :33030
使用pin的-appdebug
选项,在程序第一条指令前暂停,并启动debugger窗口。在另一个窗口里gdb通过pid连接:
$ gdb fibonacci #如果没指定应用obj-intel64/fibonacci.exe
(gdb) target remote :33030 #连接gdb端口
(gdb) file obj-intel64/fibonacci.exe #如果没指定应用, 需要指定程序来加载symbols
(gdb) b main #continue 等正常操作
能够在上一小节的debug窗口里,通过自定义debug指令打印自定义程序相关信息(比如当前stack使用大小)
Pintool “stack-debugger” 能够监控每条分配stack空间的指令,并当stack使用达到阈值时stop at a breakpoint。
这功能由两部分代码实现,一个是插桩代码,一个是分析代码。
static VOID Instruction(INS ins, VOID *)
{
if (!EnableInstrumentation) // ROI(Region of interest)开始插桩测量
return;
if (INS_RegWContain(ins, REG_STACK_PTR)) //判断指令是不是会改变stack指针(allocate stack)
{
IPOINT where = IPOINT_AFTER;
if (!INS_IsValidForIpointAfter(ins))
where = IPOINT_TAKEN_BRANCH; //寻找stack空间判断函数插入位置(指令执行完的位置)。如果不是after, 就是taken branch
INS_InsertIfCall(ins, where, (AFUNPTR)OnStackChangeIf, IARG_REG_VALUE, REG_STACK_PTR,
IARG_REG_VALUE, RegTinfo, IARG_END); // 插入OnStackChangeIf函数,如果OnStackChangeIf()返回non-zero, 执行下面的DoBreakpoint函数
INS_InsertThenCall(ins, where, (AFUNPTR)DoBreakpoint, IARG_CONST_CONTEXT, IARG_THREAD_ID, IARG_END);
}
}
所需的两个函数的分析代码如下:
static ADDRINT OnStackChangeIf(ADDRINT sp, ADDRINT addrInfo)
{
TINFO *tinfo = reinterpret_cast<TINFO *>(addrInfo);
// The stack pointer may go above the base slightly. (For example, the application's dynamic
// loader does this briefly during start-up.)
//
if (sp > tinfo->_stackBase)
return 0;
// Keep track of the maximum stack usage.
//
size_t size = tinfo->_stackBase - sp;
if (size > tinfo->_max)
tinfo->_max = size; //更新stack使用大小
// See if we need to trigger a breakpoint.
//
if (BreakOnNewMax && size > tinfo->_maxReported)
return 1;
if (BreakOnSize && size >= BreakOnSize)
return 1;
return 0;
}
static VOID DoBreakpoint(const CONTEXT *ctxt, THREADID tid)
{
TINFO *tinfo = reinterpret_cast<TINFO *>(PIN_GetContextReg(ctxt, RegTinfo));
// Keep track of the maximum reported stack usage for "stackbreak newmax".
//
size_t size = tinfo->_stackBase - PIN_GetContextReg(ctxt, REG_STACK_PTR);
if (size > tinfo->_maxReported)
tinfo->_maxReported = size;
ConnectDebugger(); // Ask the user to connect a debugger, if it is not already connected.
// Construct a string that the debugger will print when it stops. If a debugger is
// not connected, no breakpoint is triggered and execution resumes immediately.
//
tinfo->_os.str("");
tinfo->_os << "Thread " << std::dec << tid << " uses " << size << " bytes of stack.";
PIN_ApplicationBreakpoint(ctxt, tid, FALSE, tinfo->_os.str());
}
OnStackChangeIf
函数监控当前的stack使用并判断是否到达阈值。DoBreakpoint
函数连接debugger窗口,然后触发breakpoint,并打印相关信息。
也可以使用-appdebug_enable
参数,取消在第一条指令前开启GDB窗口的功能,而是在触发如上代码的break时,才开启GDB窗口的连接。
而上述代码中的ConnectDebugger
函数实现如下:
static void ConnectDebugger()
{
if (PIN_GetDebugStatus() != DEBUG_STATUS_UNCONNECTED) //判断是不是已有debugger连接
return;
DEBUG_CONNECTION_INFO info;
if (!PIN_GetDebugConnectionInfo(&info) || info._type != DEBUG_CONNECTION_TYPE_TCP_SERVER) //PIN_GetDebugConnectionInfo()获取GDB所需的tcp连接端口
return;
*Output << "Triggered stack-limit breakpoint.\n";
*Output << "Start GDB and enter this command:\n";
*Output << " target remote :" << std::dec << info._tcpServer._tcpPort << "\n";
*Output << std::flush;
if (PIN_WaitForDebuggerToConnect(1000*KnobTimeout.Value())) //等待其余GDB窗口的连接
return;
*Output << "No debugger attached after " << KnobTimeout.Value() << " seconds.\n";
*Output << "Resuming application without stopping.\n";
*Output << std::flush;
}
这部分讲述了如何debug Pintool中的问题。(对Pintool的原理也能更了解
为此,pin使用了-pause_tool n
暂停n秒等待gdb连接。
../../../pin -pause_tool 10 -t /staff/shaojiemike/github/sniper_PIMProf/pin_kit/source/tools/ManualExamples/obj-intel64/stack-debugger.so -- obj-intel64/fibonacci.exe 1000
Pausing for 10 seconds to attach to process with pid 3502000
To load the debug info to gdb use:
*****************************************************************
set sysroot /not/existing/dir
file
add-symbol-file /staff/shaojiemike/github/sniper_PIMProf/pin_kit/source/tools/ManualExamples/obj-intel64/stack-debugger.so 0x7f3105f24170 -s .data 0x7f31061288a0 -s .bss 0x7f3106129280
*****************************************************************
注意gdb对象既不是pin
也不是stack-debugger.so
,而是intel64/bin/pinbin
。原因是intel64/bin/pinbin
是pin
执行时的核心程序,通过htop
监控可以看出。
# shaojiemike @ snode6 in ~/github/sniper_PIMProf/pin_kit/source/tools/ManualExamples on git:dev x [19:57:26]
$ gdb ../../../intel64/bin/pinbin
(gdb) attach 3502000
这时GDB缺少了stack-debugger.so
的调试信息,需要手动添加。这里的add-symbol-file
命令是在pin
启动时打印出来的,直接复制粘贴即可。
(gdb) add-symbol-file /staff/shaojiemike/github/sniper_PIMProf/pin_kit/source/tools/ManualExamples/obj-intel64/stack-debugger.so 0x7f3105f24170 -s .data 0x7f31061288a0 -s .bss 0x7f3106129280
(gdb) b main #或者 b stack-debugger.cpp:94
gef➤ info b
Num Type Disp Enb Address What
1 breakpoint keep y <MULTIPLE>
1.1 y 0x00000000000f4460 <main> # 无法访问的地址,需要去除
1.2 y 0x00007f3105f36b65 in main(int, char**) at stack-debugger.cpp:94
(gdb) del 1.1
(gdb) c
stack-debugger.so
的调试信息,无法设置断点。暂无
暂无