我们使用:cmake3 --build /mnt/vdb1/vpp/build-root/build-vpp_debug-native/vpp
编译了 vpp
在次之前执行了make install-ext-deps
,DPDK各种库文件已经安装,模块已经安装到了内核,
现在我们要分析一下入口函数。
进入目录:/mnt/vdb1/vpp/build-root/build-vpp_debug-native/vpp
nm -al bin/vpp 生成符号表,带源文件地址。
objdump -j .text -Sl bin/vpp --prefix-addresses > debug.info 反汇编,汇编和C语言混合。
上面生成以备后用。
调试使用cgdb.
[root@devel-ng-exporter-225 vpp]# pwd
/mnt/vdb1/vpp/build-root/build-vpp_debug-native/vpp
[root@devel-ng-exporter-225 vpp]# cgdb bin/vpp
/usr/bin/vpp -c /etc/vpp/startup.conf
我们先看一下用户态程序的参数传递规则:
int
main (int argc, char *argv[])
{
00000000004066b5 <main> push %rbp #上一个调用函数的执行指针压栈
00000000004066b6 <main+0x1> mov %rsp,%rbp #rbp本帧的栈开始
00000000004066b9 <main+0x4> sub $0x1160,%rsp #本帧栈结束
00000000004066c0 <main+0xb> mov %edi,-0x1154(%rbp) #第一个参数入栈
00000000004066c6 <main+0x11> mov %rsi,-0x1160(%rbp)#第二个参数入栈
00000000004066cd <main+0x18> mov %fs:0x28,%rax
00000000004066d6 <main+0x21> mov %rax,-0x8(%rbp)
00000000004066da <main+0x25> xor %eax,%eax
tips:
C语言x86_64的整形和指针型的参数传递是rdi,rsi,rdx,rcx,r8,r9中,多于这些寄存器的参数会被保存在栈上。并且要注意的是断点不会指向函数的开头,而是执行地址偏后一些的源码级别的开头。
182│ static inline int
183│ clib_get_cpuid (const u32 lev, u32 * eax, u32 * ebx, u32 * ecx, u32 * edx)
184│ {
185├>if ((u32) __get_cpuid_max (0x80000000 & lev, 0) < lev)
186│ return 0;
187│ if (lev == 7)
188│ __cpuid_count (lev, 0, *eax, *ebx, *ecx, *edx);
189│ else
190│ __cpuid (lev, *eax, *ebx, *ecx, *edx);
191│ return 1;
192│ }
注意:从上图可以看到他把传递的参数都压栈了(rdi,rsi,rdx,rcx,r8)
当前帧的结束地址
(gdb) info r rsp
rsp 0x7fffffffd070 0x7fffffffd070
1 解析文件:/etc/vpp/startup.conf
while (1)
{
if (fgets (inbuf, 4096, fp) == 0)
break;
p = strtok (inbuf, " \t\n");
while (p != NULL)
{
if (*p == '#')
break;
argc_++;
char **tmp = realloc (argv_, argc_ * sizeof (char *));
if (tmp == NULL)
return 1;
argv_ = tmp;
arg = strndup (p, 1024);
if (arg == NULL)
return 1;
argv_[argc_ - 1] = arg;
p = strtok (NULL, " \t\n");
}
}
上面程序很精简,并不复杂得到下面的结果:
(gdb) p argv_[0]
$24 = 0x6ff2f0 "/mnt/vdb1/vpp/build-root/build-vpp_debug-native/vpp/bin/vpp"
(gdb) p argv_[1]
$25 = 0x6ff340 "unix"
(gdb) p argv_[2]
$26 = 0x6ff360 "{"
(gdb) p argv_[3]
$27 = 0x6ff2d0 "nodaemon"
(gdb) p argv_[4]
$28 = 0x6ff3b0 "log"
(gdb) p argv_[5]
$29 = 0x6ff410 "/var/log/vpp/vpp.log"
设置main程序亲和性,main_core默认为1,可在文件中配置。
# https://fdio-vpp.readthedocs.io/en/latest/gettingstarted/users/configuring/startup.html
#heapsize 2G
#Alternate syntax to choose plugin path. Plugin_path configuration
#controls the set of directories searched for vlib plugins. Supply
# a colon-separated list of (absolute) directory
#names: plugin_path dir1:dir2:…:dirN
#plugin_path /home/bms/vpp/build-root/install-vpp-native/vpp/lib/vpp_plugins
#test_plugin_path
#main-core <n>
#Assign main thread to a specific core.
main-core 1
unix {
nodaemon
log /var/log/vpp/vpp.log
full-coredump
cli-listen localhost:5002
}
api-trace {
on
}
dpdk {
dev 0000:00:08.0
}
关于/etc/vpp/startup.conf中参数和使用配置参考:https://fdio-vpp.readthedocs.io/en/latest/gettingstarted/users/configuring/startup.html
设置main程序的亲和性:
/* set process affinity for main thread */
CPU_ZERO (&cpuset);
CPU_SET (main_core, &cpuset);
pthread_setaffinity_np (pthread_self (), sizeof (cpu_set_t), &cpuset);
272│ /* Set up the plugin message ID allocator right now... */
273├> vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
上面完成: