我希望我的异常处理程序和调试函数能够打印调用堆栈回溯,基本上就像glibc中的backtrace()库函数一样.不幸的是,我的C库(Newlib)没有提供这样的调用.
我有这样的事情:
#include <unwind.h> // GCC's internal unwinder, part of libgcc
_Unwind_Reason_Code trace_fcn(_Unwind_Context *ctx, void *d)
{
int *depth = (int*)d;
printf("\t#%d: program counter at %08x\n", *depth, _Unwind_GetIP(ctx));
(*depth)++;
return _URC_NO_REASON;
}
void print_backtrace_here()
{
int depth = 0;
_Unwind_Backtrace(&trace_fcn, &depth);
}
Run Code Online (Sandbox Code Playgroud)
这基本上有效,但结果痕迹并不总是完整的.例如,如果我这样做
int func3() { print_backtrace_here(); return 0; }
int func2() { return func3(); }
int func1() { return func2(); }
int main() { return func1(); }
Run Code Online (Sandbox Code Playgroud)
backtrace只显示func3()和main().(这是一个玩具示例,但我已经检查了反汇编并确认这些功能全部都在这里,并没有优化或内联.)
更新:我在旧的ARM7系统上尝试了这个回溯代码但是使用相同(或至少,尽可能等同)的编译器选项和链接描述文件,它打印出正确的完整回溯(即func1和func2不会丢失)和实际上它甚至会将过去的主要内容转移到启动初始化代码中.所以可能问题不在于链接器脚本或编译器选项.(另外,通过反汇编确认在此ARM7测试中也没有使用帧指针).
代码使用-fomit-frame-pointer编译,但我的平台(裸机ARM Cortex M3)定义了一个不使用帧指针的ABI.(该系统的先前版本在ARM7上使用旧的APCS ABI,具有强制堆栈帧和帧指针,以及类似于此处的回溯,它完美地工作).
整个系统使用-fexception进行编译,这确保了_Unwind使用的必要元数据包含在ELF文件中.(_Unwind是为我认为的异常处理而设计的).
所以,我的问题是: 在使用GCC的嵌入式系统中,是否存在"标准",可接受的可靠回溯方式? …
我正在为ARM Cortex-M3(NXP的LCP17xx)创建代码.到目前为止我一直在使用静态内存,一切运行良好.我试图添加动态内存支持,但是一旦我调用malloc,系统就会卡住.
我正在用gcc编译arm裸机,并使用newlib.版本:gcc-arm-none-eabi-4_6-2012q1
为了添加malloc支持,我实现了一个简单的_sbrk函数并修改了我的链接器脚本以为堆创建一些空间(我已经阅读了很多关于这个部分的不同教程,但没有一个涵盖我接下来遇到的问题).
在一些LED的帮助下,我可以确定代码运行到它调用的那一点malloc
,然后它就不会继续.它甚至没有达到我的_sbrk
功能.此外,sizeof
如果我malloc
稍后在代码中包含一个调用,它将陷入调用状态.
那么,当调用malloc
代码时,如果没有达到_sbrk
或返回代码,我会做错什么呢?
在对malloc
包含调用时生成的内存映射进行了很长一段时间后,当它不是时,我怀疑它与使用的结构有关malloc
.
这是定义ram内存的ld脚本的一部分:
.bss :
{
_start_bss = .;
*(.bss)
*(COMMON)
_ebss = .;
. = ALIGN (8);
_end = .;
} >sram
. = ALIGN(4);
_end_bss = .;
. = ALIGN(256);
_start_heap = .;
PROVIDE( __cs3_heap_start = _start_heap)
_end_stack = 0x10008000;
Run Code Online (Sandbox Code Playgroud)
然后在中断向量表中设置_end_stack.
现在比较不同的地图.不在代码中使用malloc:
*(COMMON)
0x1000000c _ebss = .
0x10000010 . = ALIGN (0x8)
*fill* 0x1000000c 0x4 00
0x10000010 …
Run Code Online (Sandbox Code Playgroud) 我有一个奇怪的问题.
数学库已添加到我的makefile中.
# include standard C library
LDFLAGS += -lc
# include standard math library
LDFLAGS += -lm
Run Code Online (Sandbox Code Playgroud)
在输出文件(.map)中,我可以看到所有内容都已正确链接:
LOAD c:/gnu/powerpc-eabi/3pp.ronetix.powerpc-eabi/bin/../lib/gcc/powerpc-eabi/4.3.3/nof\libgcc.a
LOAD c:/gnu/powerpc-eabi/3pp.ronetix.powerpc-eabi/bin/../lib/gcc/powerpc-eabi/4.3.3/../../../../powerpc-eabi/lib/nof\libc.a
LOAD c:/gnu/powerpc-eabi/3pp.ronetix.powerpc-eabi/bin/../lib/gcc/powerpc-eabi/4.3.3/../../../../powerpc-eabi/lib/nof\libm.a
Run Code Online (Sandbox Code Playgroud)
当我做
z = pow((double) 2, (double) 3);
Run Code Online (Sandbox Code Playgroud)
它工作正常.但是,如果我测试另一个函数,如:
double result = asin(x);
Run Code Online (Sandbox Code Playgroud)
我去拿:
undefined reference to `asin'
collect2: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
怎么会这样?在math.h中都有pow和asin,见下文:
/* Non reentrant ANSI C functions. */
#ifndef _REENT_ONLY
#ifndef __math_6881
extern double acos _PARAMS((double));
extern double asin _PARAMS((double));
extern double atan2 _PARAMS((double, double));
extern …
Run Code Online (Sandbox Code Playgroud) 我从http://newlib.sourcearchive.com/documentation/1.18.0/init_8c-source.html查看了__libc_init_array的源代码.
但我不太明白这个功能是做什么的.
我知道这些符号
/* These magic symbols are provided by the linker. */
extern void (*__preinit_array_start []) (void) __attribute__((weak));
extern void (*__preinit_array_end []) (void) __attribute__((weak));
extern void (*__init_array_start []) (void) __attribute__((weak));
extern void (*__init_array_end []) (void) __attribute__((weak));
extern void (*__fini_array_start []) (void) __attribute__((weak));
extern void (*__fini_array_end []) (void) __attribute__((weak));
Run Code Online (Sandbox Code Playgroud)
在链接描述文件中定义.
链接器脚本的一部分可能如下所示:
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN …
Run Code Online (Sandbox Code Playgroud) 我正在使用STMicroelectronics的STM32F746NG微控制器.该器件基于ARM Cortex-M7架构.我花了很多时间来理解示例项目中的linkerscript.我想出了基础知识,但我仍然无法掌握它的大部分内容.请帮我理解这些部分.
linkerscript开头如下:
/* Entry Point */
ENTRY(Reset_Handler) /* The function named 'Reset_Handler' is defined */
/* in the 'startup.s' assembly file. */
/* Highest address of the user mode stack */
/* Remember: the stack points downwards */
_estack = 0x20050000; /* End of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200; /* Required amount of heap */
_Min_Stack_Size = 0x400; /* Required amount of stack */ …
Run Code Online (Sandbox Code Playgroud) 我正在尝试交叉编译一个文件以闪入 Beaglebone Black。一切正常,但如果我尝试启用 FPU
#define set_en_bit_in_fpexc() do { \
int dummy; \
__asm__ __volatile__ ("fmrx %0,fpexc\n\t" \
"orr %0,%0,#0x40000000\n\t" \
"fmxr fpexc,%0" : "=r" (dummy) : :); \
} while (0)
Run Code Online (Sandbox Code Playgroud)
我收到以下错误
Error: selected processor does not support `fmrx r3,fpexc' in ARM mode
Error: selected processor does not support `fmxr fpexc,r3' in ARM mode
Run Code Online (Sandbox Code Playgroud)
我也尝试过thumb mode
,但我遇到了同样的错误。当然,如果我删除初始化 FPU 的代码部分,它就可以正常工作。
为什么我会收到这些错误?
生成文件
[...]
CROSSPATH?=/usr/bin
CROSSPFX=$(CROSSPATH)/arm-none-eabi-
CC=$(CROSSPFX)gcc
AS=$(CROSSPFX)as
LD=$(CROSSPFX)ld
NM=$(CROSSPFX)nm
OBJCOPY=$(CROSSPFX)objcopy
OBJDUMP=$(CROSSPFX)objdump
CFLAGS=-Wall -Wextra -O2 -ffreestanding
ARCHFLAGS=-mcpu=cortex-a8 -march=armv7-a -mfpu=neon
CCARCHFLAGS=$(ARCHFLAGS) -marm …
Run Code Online (Sandbox Code Playgroud) 我正在尝试为我的操作系统移植NewLib(我正在关注本教程:http://wiki.osdev.org/Porting_Newlib ),我有一些问题.
一旦LibGloss完成并编译,我何时必须使用已创建的libnosys.a?是在我编译main.c的时候吗?
mipsel-uknown-elf-gcc main.c -Llibnosys.a`
Run Code Online (Sandbox Code Playgroud)我的crt0.c完成了.我必须"将它作为第一个对象链接".我怎样才能做到这一点?这是这样的吗?
mipsel-uknown-elf-ld crt0.o main.o
Run Code Online (Sandbox Code Playgroud)谢谢你的回答!
我想使用newlib而不是glibc来编译小的静态二进制文件.(我不打算交叉编译,因为二进制文件将由同一台计算机使用.)我相信我需要为此编译一个单独的gcc?
我编译了gcc:
./configure --prefix=/home/myuser/Desktop/gcc-4.4.5 --libexecdir=/home/myuser/Desktop/gcc-4.4.5 --libdir=/home/myuser/Desktop/gcc-4.4.5 --with-gxx-include-dir=/home/myuser/Desktop/gcc-4.4.5 --enable-languages=c --enable-libmudflap --disable-multilib --disable-libssp --disable-nls --with-newlib --with-gnu-as --with-gnu-ld --with-system-zlib make
它编译没有错误,但现在我尝试编译一个简单的Hello World!程序它想要使用来自/ usr的头文件而不是我上面指定的路径.这些是一些错误:
In file included from /home/myprogram/Desktop/myprogram.c:1: /usr/include/stdio.h:34:21: error: stddef.h: No such file or directory In file included from /usr/include/stdio.h:75, from /home/myprogram/Desktop/myprogram.c:1: /usr/include/libio.h:53:21: error: stdarg.h: No such file or directory In file included from /usr/include/stdio.h:75, from /home/myprogram/Desktop/myprogram.c:1: /usr/include/libio.h:332: error: expected specifier-qualifier-list before 'size_t' /usr/include/libio.h:364: error: expected declaration specifiers or '...' before 'size_t' /usr/include/libio.h:373: error: expected declaration specifiers or '...' before 'size_t'
我究竟做错了什么 …
我有自己的执行_open()
,_close()
,_write()
,_read()
.
我的代码:
FILE *f = fopen("0:test", "wb"); // calls _open()
fwrite("hello ", 6, 1, f);
fwrite("world\r\n\0", 8, 1, f); // calls _write(3, "hello world\r\n", 13)
fflush(f); // calls _write(3, "\0", 1)
fclose(f); // calls _close(3)
Run Code Online (Sandbox Code Playgroud)
BUFSIZE
是1024
编译器:arm-none-eabi-gcc
/版本:5.4.1
即使我有旗帜,为什么要fwrite()
解释?'\n'
"wb"
是否fopen()
解释文件名"0:test"
?
我从https://developer.arm.com/open-source/gnu-toolchain/gnu下载了工具链“ gcc-arm-none-eabi-6-2017-q2-update-win32-sha1.exe ”(Windows)-rm/downloads并将其安装在我的 Windows 10 PC 上。
安装文件夹在“ ../share/doc/gcc-arm-none-eabi/ ”中包含一个 release.txt ,它告诉:
此版本包括以下项目:
- newlib 和 newlib-nano : git://sourceware.org/git/newlib-cygwin.git commit 0d79b021a4ec4e6b9aa1a9f6db0e29a137005ce7
“ ../share/doc/gcc-arm-none-eabi/ ”中的 readme.txt 还包含:
- C 库使用 *
该工具链与两个基于 newlib 的预构建 C 库一起发布:一个是标准的 newlib (libc.a),另一个是代码大小的 newlib-nano (libc_nano.a)。
现在我想完全重建“ ../arm-none-eabi/lib/thumb ”中包含的所有 libc.a 和 libc_nano.a
目前我可以使用“ gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2 ”在Ubuntu上构建
$ # Downloaded newlib-cygwin (with corresponding hash) into folder newlib-cygwin
$ mkdir build
$ cd build
$ ../newlib-cygwin/configure --target=arm-none-eabi --disable-newlib-supplied-syscalls
$ make
Run Code Online (Sandbox Code Playgroud)
我必须如何配置 newlib 以构建 gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2 中包含的 libc.a 和 libc_nano.a …