问题标签 [freestanding]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
0 回答
175 浏览

c++ - 使用带有 -ffreestanding 的 Clang-6.0 进行编译时,由于签名不匹配而导致对 main() 的未定义引用

我正在开发一个操作系统内核作为一种爱好,并且我已经有一个库可以在托管和独立环境中替换标准库。自然地,它提供了进行必要设置和调用的入口点main()

main()在托管环境中,声明的签名和实际main()定义中的签名是否不完全匹配似乎无关紧要。但是,一旦我添加了-ffreestanding编译标志,链接器就无法再解析这样的引用。请参阅下面的最小示例:

启动.cpp

主文件

命令行:

由于 GCC 7.3.0 成功编译了此示例,因此这种行为似乎是 Clang 特有的。

我的问题是如何允许上述示例并在一般情况下工作,以及我遇到的问题是否是 Clang 错误。


更新1:

原来,解决这个问题的方法是添加__attribute__((weak))main(). 但是,如果有人可以更详细地解释这通常如何与main().

更新 2:

显然,将其标记main()为弱符号可以在没有链接的情况下进行链接main(),这显然不是它通常的工作方式(考虑到 SO 上的所有其他“未定义对主要的引用”问题)。那么 ifmain()通常不是一个弱符号,它是如何真正起作用的呢?

更新 3:

事实证明,弱符号根本不是解决方案,因为与它一起使用时只会隐藏从未解决且根本不调用实际符号-ffreestanding的事实。但是在托管环境中,它仍然像往常一样被调用。这似乎越来越像一个 Clang 错误。int main(int argc, char *argv[], char *envp[])int main()_start()

0 投票
0 回答
190 浏览

gcc - 为什么添加独立选项后 printf 功能仍然可用

一般来说,我已经阅读了以下文章,检查了 gcc 语言标准中的“独立/托管”定义,但还没有解决我的疑问。

https://gcc.gnu.org/onlinedocs/gcc/Standards.html

https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html

独立的 GCC 和内置函数

我在 Win7 中使用托管的 gcc/cygwin。我发现生成的 .out、.map 或 .exe 文件对于使用 -ffreestanding 和不使用 -ffreestanding 的不同构建是相同的。

C文件(test.c):

下面列出了 2 个不同构建的命令行:

test1.exe 和 test2.exe 都可以通过构建并在运行时打印“test1”。但我曾认为使用 -ffreestanding 编译可能会由于“找不到 stdio 头”、“不包含标准库”或“找不到 printf 实现”而失败。

似乎即使使用 -ffreestanding 选项,托管的 gcc 也不能作为独立的 gcc 工作。

谁能帮忙澄清一下?为什么添加独立选项后 printf 功能仍然可用?

0 投票
0 回答
78 浏览

c++ - 自定义独立 printf 仅显示一个字母和随机大写 S

我正在尝试开发我自己的内核,我正在使用 GRUB 引导它。

为了显示带有变量的字符串,我已经开始开发自己的printf(char*, ...)函数。

这是 kernel.cpp(感谢Write Your Own Operating System YouTube tutorial for main loading part(printf 完全是我的代码))

结果: 在此处输入图像描述

如您所见,它显示第一个字符和“S”。

如果我将消息更改为“我的自定义内核”,结果如下:

在此处输入图像描述

正如您在此处看到的,它再次打印第一个字母,然后是“S”。

为什么会这样?据我了解, va_args 更改charint,但这并不能解释为什么它只显示第一个字母和“S”。

为什么会发生这种情况,我该如何解决?

编辑:这也已经用标志编译:-m32 -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore

0 投票
1 回答
86 浏览

windows - 编译我自己的内核时对“WinMain”的未定义引用

我已经开始编写自己的内核并在 Windows 10 上进行开发。

我正在使用以下工具:

  • gcc 8.1.0 elf x86_64 用于编译我的 C 代码和链接。
  • nasm 2.14.02 用于编译我的汇编代码。

我正在使用以下命令来构建我的独立内核代码:

我正在使用以下命令来编译根汇编代码:

最后,我将目标文件链接在一起:

我不知道为什么,但以下错误使链接过程停止工作:

这对我来说没有意义,因为我的编译和链接处于独立模式,并且我没有尝试使用任何 Windows API。

我该如何解决?


如果重要的话,这是我非常简单的代码:

main.asm

kernel.c


编辑:看起来我可能需要x86_64-elf-gcc编译器

编辑2:我尝试了x86_64-w64-mingw32-gcc编译器,出现同样的错误

0 投票
1 回答
196 浏览

c - Subtleties dealing with cross compilation, freestanding libgcc, etc

I have a few questions about https://wiki.osdev.org/Meaty_Skeleton, which says:

The GCC documentation explicitly states that libgcc requires the freestanding environment to supply the memcmp, memcpy, memmove, and memset functions, as well as abort on some platforms. We will satisfy this requirement by creating a special kernel C library (libk) that contains the parts of the user-space libc that are freestanding (doesn't require any kernel features) as opposed to hosted libc features that need to do system calls

Alright, I understand that libgcc is a 'private library' that is used by gcc, i.e. It has significance only during the compilation process, when gcc is in use, kind of like a helper for gcc. Is this right? I understand that the machine I run gcc on is called the build machine, and the host machine is my own OS. What is the freestanding environment specified here? Since gcc runs on the build machine, libgcc must use the build machine libgcc I guess? Where does freestanding come into the picture?

Also, what is the libk? I think that I really don't understand freestanding and hosted environments yet :(

0 投票
1 回答
112 浏览

c - 为什么这两个应该相同的指针指向不同的数据?

我正在用 GNU C 为一个爱好操作系统编写一个 FAT16 驱动程序,我有一个这样定义的结构:

我的印象是name与整个结构在同一个地址,然后attrib是 11 个字节。实际上,(void *)e.name - (void *)&e是 0 和(void *)&e.attrib - (void *)&e11,其中e是 类型struct directory_entry

在我的内核中,指向的 void 指针e被传递给从磁盘读取其内容的函数。在这个函数之后,*(uint8_t *)&e是 80 和*((uint8_t *)&e + 118,正如预期的磁盘上的内容。但是,e.name[0]两者e.attrib都是 0。

这里给出了什么?我误解了它的__attribute__ ((packed))工作原理吗?具有相同属性的其他结构按照我对内核其他部分的期望工作。如果需要,我可以发布完整来源的链接。

编辑:完整的源代码在这个 gitlab 存储库中,在stack-overflow分支上。相关部分是 src/kernel/main.c 的第 34 到 52 行。当我检查*(uint8_t *)&e*((uint8_t *)&e + 11). 当我运行它时,该部分输出以下内容:

我很困惑为什么e.name[0]会与*(uint8_t *)&e.

编辑 2:我使用 objdump 反汇编了这部分,看看编译后的代码有什么不同,但现在我更加困惑了。 u8_dec(*(uint8_t *)&e, nbuf);并且u8_dec(e.name[0], nbuf);都编译为:(我的评论)

正如预期的那样,这会传入结构的第一个字节。我确信它u8_dec不会修改 e,因为它的第一个参数是按值传递的,而不是按引用传递的。nbuf是在文件范围内声明的数组,而e在函数范围内声明,所以它们不是重叠或任何东西。也许u8_dec没有做好它的工作?这是它的来源:

现在很清楚,打包结构确实按照我的想法工作,但我仍然不确定是什么导致了问题。我将相同的值传递给应该是确定性的函数,但是在不同的调用中得到不同的结果。

0 投票
2 回答
183 浏览

operating-system - 专用于一个程序的计算机

我想让一台计算机只运行一个程序,所以每当计算机启动时,它都会执行该程序。

例如:特斯拉汽车的电脑板,常见的超市系统

我如何使用它的一个例子:开发一个系统来使房子自动化,所以会有一个屏幕显示可以打开或关闭的灯,如果房子没电了,当能量恢复时,计算机会重新启动并再次显示灯光选项。

我必须为此构建一个操作系统吗?

0 投票
1 回答
47 浏览

c - 字符显然没有在 C 内核中转换为它的 ASCII 值

我正在 Kali 机器上开发一个基本的 C 内核并在 QEMU 中对其进行测试。这是内核代码:

这将打印Z而不是A, 但如果我用"A", 的 ASCII 值替换它A0x41它会按预期工作并打印A到屏幕上。此外,我也收到此错误:

如果我理解正确,编译器会认为我正在尝试将vidMem自身的值更改为不同数据类型的不同值;但是,我取消了对vidMem变量的引用,并且只更改了 指向的内存字节vidMem,所以我对为什么会收到此错误感到困惑。"A"当我替换为时,我没有收到错误0x41,所以我所看到的只是编译器的处理"A"方式0x41不同。为什么会这样?如何打印我想要的字符而不需要提供其 ASCII 值?

0 投票
2 回答
175 浏览

c++ - arduino 的 C++ 是否遵循标准?

Arduino平台上的C++程序没有main()其他平台上的功能;相反,它必须有两个名为setup()和的函数loop()。但根据 C++ 标准 - 所有 C++ 程序都必须有一个main()函数。

那么,这样的 C++ 代码是否符合标准?Arduino 上的 C++ 编译器/链接器/加载器是否符合标准?

0 投票
2 回答
876 浏览

gcc - 如何防止 GCC 在链接时优化期间插入 memset?

在为 RV32IM 目标 (RISC-V) 用 C 语言开发裸机固件时,我在启用 LTO 时遇到了链接错误:

但是,我的固件中没有调用memset。由memsetGCC 在优化期间插入,如此处所述-Os该构建使用 GCC和-flto -fuse-linker-plugin标志针对大小进行了优化。此外,这些-fno-builtin-memset -nostdinc -fno-tree-loop-distribute-patterns -nostdlib -ffreestanding标志用于防止memset在优化期间使用,并且不包括标准库。

memsetLTO期间如何防止插入?请注意,固件不应与 libc 链接。我还尝试提供自定义实现,memset但链接器不想memset在优化期间将其用于插入(仍然抛出未定义的引用)。