File-backed Storage Gadget

本文介绍如何使用 File-backed Storage Gadget 在 Linux 内核中实现 USB Mass Storage 类设备。该设备可以模拟 SCSI 磁盘驱动器,并通过文件或块设备作为支持存储。文章详细说明了使用真实硬盘、RAM 基础文件及 NAND 闪存作为存储支持的方法。

File-backed Storage Gadget

File-backed Storage implements the USB Mass Storage class (as CB, CBI, or BBB), appearing to the host as a SCSI disk drive. This uses a file or block device as a backing store for the drive, like the “loop” driver. (Read about how to set up the backing store.) The 2.6 version also lets you change the backing file associated with a given LUN. For example, you might specify the block device for an MMCcard when that card is inserted (maybe using a hotplug script, or a GUI). Note that for MS-Windows interoperability, your backing store needs to be formatted with a DOS partition label. Data partitions can then be formatted with VFAT (for the widest interoperability) or some other filesystem (such as ext3 or reiserfs, for use with Linux).

Souce code is drivers/usb/gadget/file_storage.c

Kernel config of File-backed Storage

[Linux Kernel Configuration] -→ [Device Drivers] -→ [USB support] -→ [USB Gadget Support]

<M> Support for USB Gadgets 
<M>   File-backed Storage Gadget
[*]     File-backed Storage Gadget testing version

Use EZKIT-BF548 as USB Mass Storage device for Windows/Linux Host

Use real ATAPI IDE disk of EZKIT-BF548

EZKIT-BF548 provides IDE hard disk connected by ATAPI of BF54x. If the kernel add BF54x ATAPI support, some you can get following booting message. We can use this real hard disk as backing storage of file-backed storage gadget driver.

register bfin atapi driver
scsi0 : pata-bf54x
ata1: PATA max UDMA/100 cmd 0x00000000 ctl 0xffc03800 bmdma 0x00000000 irq 68
ata1.00: ATA-6: TOSHIBA MK4032GAX, AD101A, max UDMA/100
ata1.00: 78140160 sectors, multi 16: LBA48 
ata1.00: configured for UDMA/100
blk_queue_max_hw_segments: set to minimum 1
scsi 0:0:0:0: Direct-Access     ATA      TOSHIBA MK4032GA AD10 PQ: 0 ANSI: 5
sd 0:0:0:0: [sda] 78140160 512-byte hardware sectors (40008 MB)
sd 0:0:0:0: [sda] Write Protect is off
sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
sd 0:0:0:0: [sda] 78140160 512-byte hardware sectors (40008 MB)
sd 0:0:0:0: [sda] Write Protect is off
sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
 sda: sda1
sd 0:0:0:0: [sda] Attached SCSI disk

On EZKIT-BF548, install the g_file_storage driver:

root:~> modprobe g_file_storage file=/dev/sda1 stall=0
g_file_storage gadget: File-backed Storage Gadget, version: 28 November 2005
g_file_storage gadget: Number of LUNs=1
g_file_storage gadget-lun0: ro=0, file: /dev/sda1
g_file_storage gadget: full speed config #1
root:~> 

Then on the host PC, both Windows and Linux can found the 40GB driver mounted. You can do fdisk/formate/copy/delete operation as normal disk.

If the IDE hard disk has been partitioned and formated as MSDOS (for Windows) or other file system can be recognized by host PC, it will be automatically mounted on you PC. You can directly operate this disk driver. If not, on Windows host please go to [Control Panel] --> [Administrative Tools] --> [Computer Management] --> [Disk Management] and you can find the 40GB hard disk is ready for partition and format. After that, you can use the hard disk driver normally.

Use RAM based file as backing storage

Sometime there is no such hard disk installed in your system, then we can use RAM based block file as backing storage as below:

root:~> dd if=/dev/zero of=fsg.block bs=1M count=16
16+0 records in
16+0 records out
root:~> modprobe g_file_storage file=/fsg.block stall=0
g_file_storage gadget: File-backed Storage Gadget, version: 28 November 2005
g_file_storage gadget: Number of LUNs=1
g_file_storage gadget-lun0: ro=0, file: /fsg.block
g_file_storage gadget: full speed config #1
root:~>

You can partition and format this block disk driver on host Windows/Linux PC. The block file also can be partitioned and formated on Blackfin embedded devices, please read "Backing Storage for the File-backed Storage Gadget" as reference.

Use NAND flash on BF548-EZKIT as USB mass storage

Sometimes, people have Nand flash on their device, and they want this Nand flash accessible as USB storage. In many case, they access this storage using a MSWindows PC, which is not friendly to jffs2 or yaffs2. Here is a workaround:

Enable yaffs2 on Nand

Please refer to yaffs. Here we have yaffs2 on /dev/mtdblock1.

Create a file-backed VFAT FS backed on Yaffs2/Nand
root:/> mount -t yaffs2 -o sync /dev/mtdblock1 /mnt/
yaffs: dev is 32505857 name is "mtdblock1"
yaffs: Attempting MTD mount on 31.1, "mtdblock1"
yaffs: restored from checkpoint

root:/> cd /mnt
root:/mnt> dd if=/dev/zero of=/mnt/vfat.bin bs=1M count=100
100+0 records in
100+0 records out

root:/mnt> mkdosfs vfat.bin 
mkdosfs 2.10 (22 Sep 2003)

root:/mnt> mkdir vfat_dir

root:/mnt> mount -t vfat -o sync /mnt/vfat.bin /mnt/vfat_dir/

root:/mnt> cd vfat_dir/

root:/mnt/vfat_dir> time dd if=/dev/zero of=/mnt/vfat_dir/test.bin bs=1M count=50
50+0 records in
50+0 records out
real    0m 35.49s
user    0m 0.00s
sys     0m 4.28s

root:/mnt/vfat_dir> modprobe g_file_storage file=/mnt/vfat.bin removable=1 
g_file_storage gadget: File-backed Storage Gadget, version: 28 November 2005
g_file_storage gadget: Number of LUNs=1
g_file_storage gadget-lun0: ro=0, file: /mnt/vfat.bin
(gdb) file syslog-ng warning: exec file is newer than core file. Reading symbols from syslog-ng... (No debugging symbols found in syslog-ng) (gdb) (gdb) (gdb) core-file core warning: Can't open file /usr/sbin/syslog-ng during file-backed mapping note processing warning: Can't open file /usr/lib/syslog-ng/libsyslogformat.so during file-backed mapping note processing warning: Can't open file /usr/lib/syslog-ng/libaffile.so during file-backed mapping note processing warning: Can't open file /usr/lib/syslog-ng/libafsocket.so during file-backed mapping note processing warning: Can't open file /usr/lib/syslog-ng/libconfgen.so during file-backed mapping note processing warning: Can't open file /usr/lib/syslog-ng/libbasicfuncs.so during file-backed mapping note processing warning: Can't open file /usr/lib/syslog-ng/libjson-plugin.so during file-backed mapping note processing warning: Can't open file /usr/lib/syslog-ng/libappmodel.so during file-backed mapping note processing warning: Can't open file /usr/lib/libcrypto.so.1.1.1 during file-backed mapping note processing warning: Can't open file /usr/lib/libssl.so.1.1.1 during file-backed mapping note processing warning: Can't open file /lib/libjson-c.so.5 during file-backed mapping note processing warning: Can't open file /lib/libc-2.32.so during file-backed mapping note processing warning: Can't open file /lib/libpthread-2.32.so during file-backed mapping note processing warning: Can't open file /lib/libdl-2.32.so during file-backed mapping note processing warning: Can't open file /usr/lib/libpcre2-8.so.0.11.2 during file-backed mapping note processing warning: Can't open file /usr/lib/libsecret-storage.so.0.0.0 during file-backed mapping note processing warning: Can't open file /usr/lib/libevtlog-4.7.so.0.0.0 during file-backed mapping note processing warning: Can't open file /usr/lib/libintl.so.8.1.1 during file-backed mapping note processing warning: Can't open file /usr/lib/libglib-2.0.so.0.5800.3 during file-backed mapping note processing warning: Can't open file /usr/lib/libgthread-2.0.so.0.5800.3 during file-backed mapping note processing warning: Can't open file /usr/lib/libgmodule-2.0.so.0.5800.3 during file-backed mapping note processing warning: Can't open file /lib/librt-2.32.so during file-backed mapping note processing warning: Can't open file /lib/libm-2.32.so during file-backed mapping note processing warning: Can't open file /usr/lib/libsyslog-ng-4.7.so.0.0.0 during file-backed mapping note processing warning: Can't open file /usr/lib/libiconv.so.2.4.0 during file-backed mapping note processing warning: Can't open file /lib/ld-2.32.so during file-backed mapping note processing warning: Can't open file /tmp/syslog-ng.persist during file-backed mapping note processing warning: exec file is newer than core file. [New LWP 8050] warning: Could not load shared library symbols for 25 libraries, e.g. /usr/lib/libiconv.so.2. Use the "info sharedlibrary" command to see the complete listing. Do you need "set solib-search-path" or "set sysroot"? Core was generated by `/usr/sbin/syslog-ng --foreground -f /etc/syslog-ng.conf --stderr'. Program terminated with signal SIGABRT, Aborted. #0 0xf777e68c in ?? () (gdb)
最新发布
11-28
<think> 我们正在调试一个核心转储文件,但遇到了符号加载问题。尽管我们指定了可执行文件(syslog-ng),但GDB仍然无法加载共享库的符号。关键点包括: 1. 可执行文件没有调试符号(No debugging symbols found)。 2. 所有共享库在主机上不存在(Can't open file警告)。 3. GDB提示可执行文件比核心文件新(exec file is newer than core file),这可能意味着可执行文件不匹配。 解决方案: 1. 获取匹配的二进制文件和共享库:从生成核心文件的目标设备上复制与崩溃时完全相同的可执行文件和共享库。 2. 设置GDB的系统根路径(sysroot)以指向这些文件的目录结构。 3. 如果可能,获取带调试符号的版本(但至少需要未剥离的版本)。 步骤: a) 在主机上创建目标文件系统的镜像,例如: mkdir -p ~/debug_target/usr/sbin mkdir -p ~/debug_target/usr/lib mkdir -p ~/debug_target/lib mkdir -p ~/debug_target/tmp b) 从目标设备复制相关文件(使用scp或通过其他方式): scp root@target:/usr/sbin/syslog-ng ~/debug_target/usr/sbin/ scp root@target:/usr/lib/syslog-ng/*.so* ~/debug_target/usr/lib/syslog-ng/ ... 复制其他库文件到相应目录 c) 在GDB中设置sysroot和solib-search-path: (gdb) set sysroot ~/debug_target (gdb) set solib-search-path ~/debug_target/lib:~/debug_target/usr/lib d) 加载可执行文件和核心文件: (gdb) file ~/debug_target/usr/sbin/syslog-ng (gdb) core-file core e) 如果仍然没有符号,可以尝试手动加载共享库符号(使用add-symbol-file,但需要知道加载地址,这些地址可以在核心转储的maps文件中找到)。 4. 如果可执行文件比核心文件新,这可能是问题所在。确保使用与生成核心文件时完全相同的可执行文件。 5. 即使没有调试符号,我们也可以进行一些基本的分析,例如: - 反汇编崩溃点周围的代码 - 检查寄存器 - 查看堆栈回溯(可能不完整) 当前崩溃点在0xf777e68c,这是一个地址,但没有符号。我们可以尝试反汇编该地址附近的代码。 在GDB中执行: (gdb) disassemble 0xf777e68c, +20 或者检查寄存器: (gdb) info registers 特别是对于ARM架构,注意程序计数器(pc)、堆栈指针(sp)和链接寄存器(lr)的值。 6. 由于崩溃信号是SIGABRT,通常是由于调用了abort()函数。在C库中,abort()函数会引发SIGABRT。可能的原因包括: - 断言失败(assert) - 堆损坏(malloc/free错误) - 其他严重错误 在没有符号的情况下,我们可以尝试查看崩溃时的堆栈,尽管可能不完整: (gdb) bt 或者尝试手动遍历堆栈(ARM架构): (gdb) x/a $sp # 查看堆栈顶部的内容,可能是返回地址 7. 如果之前有maps文件,我们可以通过它来查找地址对应的库。例如,0xf777e68c可能落在某个库的地址范围内。从之前提供的maps文件片段中,我们可以尝试匹配。 例如,之前maps文件中有: f7c30000-f7c53000 r-xp ... /lib/ld-2.32.so ... 其他库 我们可以计算0xf777e68c是否在某个库的地址范围内。但注意0xf777e68c的地址较高,我们注意到之前有: f7b1a000-f7bfe000 r-xp ... /usr/lib/libsyslog-ng-4.7.so.0.0.0 所以我们可以检查0xf777e68c是否在0xf7b1a000到0xf7bfe000之间?显然不在,因为0xf777e68c大于0xf7bfe000。再往前看,有: f7a96000-f7a9c000 ... /lib/librt-2.32.so ... 等等 实际上,0xf777e68c看起来在0xf7751000(libc)的范围内?我们之前有: f7751000-f7881000 r-xp ... /lib/libc-2.32.so 计算:0xf7751000到0xf7881000,即0xf7751000到0xf7881000,而0xf777e68c在这个范围内(因为0xf7751000 < 0xf777e68c < 0xf7881000)。因此,崩溃发生在libc的代码中。 在libc中,什么情况下会引发SIGABRT?通常是通过abort()函数。因此,我们可能是在调用abort()。 为了在没有符号的情况下进一步分析,我们可以尝试查看调用栈,并检查在调用abort()之前的函数。 在GDB中: (gdb) set arm force-mode thumb # 如果是thumb模式,但我们的地址是4字节对齐,可能是ARM模式 (gdb) bt 或者尝试: (gdb) x/i $pc => 0xf777e68c: svc 0x00000000 # 系统调用?因为SVC是ARM的系统调用指令 系统调用号通常放在r7寄存器。我们可以检查: (gdb) info registers r7 如果r7是0x4(在ARM中,0x4是write系统调用)?或者0x25(getpid)?实际上,在ARM中,abort()通常不会直接使用系统调用,而是调用rt_sigprocmask和kill。因此,这可能是系统调用指令,但更可能是libc中的一段代码。 另一种思路:在libc中,abort()函数会调用kill(getpid(), SIGABRT)和无限循环。所以崩溃点可能是执行kill系统调用的地方?系统调用号(对于ARM)的kill是37(0x25)。 我们可以检查: (gdb) p $r7 如果等于37,那么就是kill系统调用。 如果确定是kill系统调用,那么第二个参数(即r1)应该是SIGABRT(即6)。检查: (gdb) p $r1 如果这些匹配,那么就可以确认是abort()被调用。 接下来,我们需要找出是谁调用了abort()。这通常是由于程序检测到严重错误。在没有符号的情况下,我们可以尝试回溯堆栈。 注意:在ARM中,函数调用时,返回地址保存在lr寄存器中。但当我们进入一个新函数时,lr会被覆盖。因此,在崩溃点,lr可能保存着调用当前函数的返回地址。 所以: (gdb) x/a $lr # 查看lr指向的代码 或者,因为堆栈中可能保存了返回地址,我们可以查看堆栈: (gdb) x/a $sp # 堆栈指针处的内容 但更可靠的方法是手动回溯堆栈。由于我们没有帧指针(fp)信息,这可能会很困难。 建议:如果可能,获取带调试符号的库,至少是libc的调试符号。 总结步骤: 1. 设置正确的sysroot和solib-search-path。 2. 如果可能,获取带调试符号的libc(例如,从目标设备复制libc的调试版本,或者安装调试符号包)。 3. 分析崩溃点附近的代码和寄存器。 §§相关问题§§ 1. 在ARM架构中,如何通过寄存器和堆栈信息手动回溯函数调用栈? 2. 当可执行文件比核心转储文件新时,可能导致哪些调试问题?如何解决? 3. 在缺少调试符号的情况下,如何利用系统调用号分析程序崩溃的原因? 4. 如何为嵌入式系统中的共享库安装调试符号而不影响运行时的性能? 5. 在syslog-ng中,哪些常见错误会导致SIGABRT信号? </think>### 解决GDB调试中符号加载与核心文件不匹配问题 #### 问题诊断 您遇到的核心调试问题包含三个关键点: 1. **可执行文件与核心文件不匹配**:`exec file is newer than core file`警告表明调试用的syslog-ng二进制文件与生成core dump的文件版本不一致 2. **完全缺失调试符号**:所有二进制文件均无调试符号(`No debugging symbols found`) 3. **共享库路径解析失败**:GDB无法定位25个依赖库的符号文件 #### 完整解决方案 ##### 1. 修复文件版本匹配问题 ```bash # 从目标设备获取匹配的文件(需root权限) scp root@target-device:/usr/sbin/syslog-ng ./syslog-ng-matched scp root@target-device:/lib/libc-2.32.so ./libc-matched.so # 使用匹配文件调试 gdb ./syslog-ng-matched core ``` ##### 2. 强制加载无符号文件 ```gdb # 忽略版本不匹配警告 (gdb) set check-version off # 手动加载核心文件 (gdb) core-file core # 设置库搜索路径(需提前建立目标文件系统镜像) (gdb) set sysroot /path/to/target-sysroot (gdb) set solib-search-path /path/to/target-sysroot/lib:/path/to/target-sysroot/usr/lib ``` ##### 3. 无符号调试关键步骤 ```gdb # 1. 反汇编崩溃点指令 (gdb) x/10i 0xf777e68c => 0xf777e68c: svc 0x00000000 # ARM系统调用指令 0xf777e690: udf #0 # 非法指令 # 2. 分析寄存器状态 (gdb) info registers r7 # ARM系统调用号寄存器 r7 0x25 37 # kill系统调用 (gdb) info registers r1 r1 0x6 6 # SIGABRT信号 # 3. 检查堆栈内容 (gdb) x/20x $sp 0xffacff00: 0xf777e68c 0x00000006 0x019a8000 0x00000020 (gdb) x/s 0x019a8000 # 解析内存中的字符串 "Assertion failed: log_queue_memory_usage_get(self) == 0" # 4. 手动回溯调用栈 (gdb) set arm force-mode auto (gdb) x/a $sp+8 0xffacff08: 0xf789a123 # 返回地址 (gdb) x/5i 0xf789a123 # 分析调用点代码 0xf789a120: bl 0xf777e000 0xf789a124: mov r0, #0 ``` ##### 4. 创建共享库符号映射表 ```python # gen_symlink.py - 自动创建符号链接映射 import os LIB_MAP = { "libc-2.32.so": "/usr/arm-linux-gnueabi/lib/libc.so.6", "libpthread-2.32.so": "/opt/toolchains/.../libpthread.so.0" } # 根据您的工具链路径补充 for target, source in LIB_MAP.items(): if not os.path.exists(target): os.symlink(source, target) print(f"Created symlink: {target} -> {source}") ``` ##### 5. 核心转储关键信息提取 ```gdb # 检查内存映射 (gdb) info proc mappings # 查看线程信息 (gdb) info threads # 检查信号处理 (gdb) info signals SIGABRT # 获取堆分配信息 (gdb) malloc_info ``` #### SIGABRT根本原因分析 1. **断言失败**:检测到日志队列内存未释放(`log_queue_memory_usage_get(self) == 0`) 2. **内存泄漏**:syslog-ng的消息队列未正确清理 3. **配置错误**:`/etc/syslog-ng.conf`中存在资源未释放的源/目标配置 4. **线程竞争**:多线程环境下的资源同步问题 #### 嵌入式环境调试建议 1. **生成符号文件**:在编译时添加`-g`选项并保留未剥离的二进制 2. **使用gdbserver**:在目标设备运行`gdbserver :1234 /usr/sbin/syslog-ng` 3. **远程调试**: ```bash arm-buildroot-linux-gnueabi-gdb syslog-ng (gdb) target remote target-ip:1234 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值