This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

博客

这是博客列表。

新闻

我的 Sshwifty 终端页面

嵌入式 SSH 终端

这是一个使用 Hugo 生成的页面,您可以在下面直接访问 SSH 终端:

{# Add a title parameter #}

如果您想嵌入一个 YouTube 视频,您可以这样做:

{# Add a title parameter #}

根据 sshwifty 的文档 Can I serve Sshwifty under a subpath such as https://my.domain/ssh?,sshwifty 不能部署在一个子目录里。为了绕过 这个限制,使用了 https://github.com/nirui/sshwifty/issues/10#issuecomment-562925134 里的黑魔法。

events{
    worker_connections 1024;
}

http{
    index index.html index.html;

    map $http_upgrade $connection_upgrade {
        default upgrade;
        '' close;
    }

    upstream sshwifty_backend {
        # Up stream Sshwifty backend server, change address accordingly
        server 10.220.179.110:8182;
    }

    server{
        listen 80;
        server_name localhost;

        location /sshwifty/socket {
            # Proxy to the websocket interface, change address accordingly
	    proxy_pass http://sshwifty_backend/sshwifty/socket;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
        }

        location /sshwifty/ {
            rewrite ^/sshwifty/assets/(.*) /sshwifty/assets/$1 break;
            rewrite ^/sshwifty/(.*) /$1 break;

            # Proxy to the landing page, change address accordingly
	    proxy_pass http://sshwifty_backend;
        }
    }
}

The configuration above will map Sshwifty to /sshwifty. If you instead want to use /sshclient however, then you need to redirect /sshwifty to /sshclient/sshwifty:

events{
    worker_connections 1024;
}

http{
    index index.html index.html;

    map $http_upgrade $connection_upgrade {
        default upgrade;
        '' close;
    }

    upstream sshwifty_backend {
        # Up stream Sshwifty backend server, change address accordingly
        server 10.220.179.110:8182;
    }

    server{
        listen 80;
        server_name localhost;

        location /sshwifty/socket {
            # Proxy to the websocket interface, change address accordingly
	    proxy_pass http://sshwifty_backend/sshwifty/socket;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
        }

        # Notice that you have to redirect the request from /sshwifty/* to /sshclient/sshwifty/*
        location ~ ^/sshwifty/assets/(.*) {
            return 301 /sshclient/sshwifty/assets/$1;
        }

        location /sshclient/ {
            rewrite ^/sshclient/(.*) /$1 break;

            # Proxy to the landing page, change address accordingly
	    proxy_pass http://sshwifty_backend;
        }
    }
}```

Debug

使用 GDB 调试 Hello World 程序

我将以一个简单的 C 语言 Hello World 程序为例,简洁地说明如何使用 GDB 调试。以下是步骤和关键命令:

1. 准备 Hello World 程序

创建 hello.c

#include <stdio.h>

int main() {
    printf("Hello, World!\n");
    int x = 10;
    x = x + 5;
    printf("x = %d\n", x);
    return 0;
}

2. 编译程序

使用 -g 选项编译以包含调试信息:

gcc -g -o hello hello.c

3. 启动 GDB

运行 GDB 并加载程序:

gdb ./hello

进入 GDB 交互界面:

(gdb)

4. 调试步骤

以下是调试 hello.c 的过程:

(1) 设置断点

在 main 函数设置断点:


(gdb) break main
Breakpoint 1 at 0x40111b: file hello.c, line 4.

(2) 运行程序

运行程序,暂停在断点:


(gdb) run
Starting program: ./hello
Breakpoint 1, main () at hello.c:4
4           printf("Hello, World!\n");

(3) 单步执行

逐行执行(next 不进入函数内部):


(gdb) next
Hello, World!
5           int x = 10;

(4) 查看变量

检查变量 x:


(gdb) print x
$1 = 10

继续执行:


(gdb) next
6           x = x + 5;
(gdb) next
7           printf("x = %d\n", x);
(gdb) print x
$2 = 15

(5) 继续运行

继续执行直到结束:


(gdb) continue
Continuing.
x = 15
[Inferior 1 (process 12345) exited normally]

(6) 退出 GDB

退出:


(gdb) quit

Hello

你好,世界!

Hello, Wrold!

Step in Glibc Source Code

在 Ubuntu 22.04 下,想要在 gdb 调试时 step in 到 printf 函数内部,需要满足两个条件:

  1. glibc(libc)必须带有调试符号,否则只能看到汇编或提示“no source available”。
  2. gdb 能找到 glibc 的源码路径,这样才能显示 C 语言源码而不是汇编。

步骤一:安装调试符号和源码

sudo apt update
sudo apt install libc6-dbg glibc-source

步骤二:解压 glibc 源码

sudo tar -xf /usr/src/glibc/glibc-*.tar.xz -C /usr/src/glibc/

解压后源码路径通常为 /usr/src/glibc/glibc-<version>/


步骤三:配置 gdb 的源码路径映射

glibc 在编译时源码路径通常是 /build/glibc-*/,而你本地源码在 /usr/src/glibc/glibc-<version>/
你需要告诉 gdb:把源码路径替换为本地实际路径

在 gdb 里输入:

set substitute-path /build/glibc-*/ /usr/src/glibc/glibc-<version>/

请将 <version> 替换为实际解压出来的目录名,比如 2.35.

注:上面的办法不管用。用下面的:

directory /usr/src/glibc/glibc-2.35/

有,可以通过以下方法让 gdb 每次自动加载源码路径,无需每次手动设置:

在你的主目录下创建或编辑 ~/.gdbinit 文件,加入如下内容:

directory /usr/src/glibc/glibc-2.35/

这样每次启动 gdb 时都会自动添加该源码路径。

如果只想对某个项目生效,可以在项目根目录下创建 .gdbinit 文件,内容同上。gdb 启动时会自动读取当前目录下的 .gdbinit

注意:

  • ~/.gdbinit 影响所有 gdb 会话。
  • 项目目录下的 .gdbinit 只影响该目录下的调试。

步骤四:gdb 调试

  1. 启动 gdb 并运行你的程序。
  2. 当执行到 printf 时,使用 stepstepi 进入。
  3. 如果一切正常,gdb 会显示 printf 的 glibc 源码。

说明

  • set substitute-path <编译时路径> <本地路径>
    这条命令告诉 gdb:当调试信息里出现 <编译时路径> 时,去 <本地路径> 查找源码。
  • 如果还是进不去源码,可能是优化级别太高(如 -O2),可尝试用 -O0 -g 重新编译你的程序。

总结:
只要安装了调试符号和源码,并正确配置 substitute-path,就可以 step in 到 printf 这样的 glibc 函数源码。