- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
对于大学类(class),我喜欢比较使用 gcc/clang 和汇编编写和编译的功能相似程序的代码大小。在重新评估如何进一步缩小某些可执行文件的大小的过程中,当我在 2 年前组装/链接的相同汇编代码现在在再次构建后增长了 10 倍以上时,我无法相信自己的眼睛(这适用于多个程序,不仅是 helloworld):
$ make
as -32 -o helloworld-asm-2020.o helloworld-asm-2020.s
ld -melf_i386 -o helloworld-asm-2020 helloworld-asm-2020.o
$ ls -l
-rwxr-xr-x 1 xxx users 708 Jul 18 2018 helloworld-asm-2018*
-rwxr-xr-x 1 xxx users 8704 Nov 25 15:00 helloworld-asm-2020*
-rwxr-xr-x 1 xxx users 4724 Nov 25 15:00 helloworld-asm-2020-n*
-rwxr-xr-x 1 xxx users 4228 Nov 25 15:00 helloworld-asm-2020-n-sstripped*
-rwxr-xr-x 1 xxx users 604 Nov 25 15:00 helloworld-asm-2020.o*
-rw-r--r-- 1 xxx users 498 Nov 25 14:44 helloworld-asm-2020.s
汇编代码是:
.code32
.section .data
msg: .ascii "Hello, world!\n"
len = . - msg
.section .text
.globl _start
_start:
movl $len, %edx # EDX = message length
movl $msg, %ecx # ECX = address of message
movl $1, %ebx # EBX = file descriptor (1 = stdout)
movl $4, %eax # EAX = syscall number (4 = write)
int $0x80 # call kernel by interrupt
# and exit
movl $0, %ebx # return code is zero
movl $1, %eax # exit syscall number (1 = exit)
int $0x80 # call kernel again
相同的 hello world 程序,使用 GNU
as
编译和 GNU
ld
(总是使用 32 位汇编)当时是 708 字节,现在已经增长到 8.5K。即使告诉链接器关闭页面对齐(
ld -n
),它仍然有将近 4.2K。
strip
平/
sstrip
ping 也没有返回。
readelf
告诉我节标题的开头在代码中要晚得多(字节 468 与 8464),但我不知道为什么。它在与 2018 年相同的架构系统上运行,Makefile 是相同的,我没有链接任何库(尤其不是 libc)。我猜想
ld
由于目标文件仍然很小,因此发生了变化,但是什么以及为什么?
cat << EOF | base64 -d | tar xj
QlpoOTFBWSZTWVaGrEQABBp////xebj/7//Xf+a8RP/v3/rAAEVARARAeEADBAAAoCAI0AQ+NAam
ytMpCGmpDVPU0aNpGmh6Rpo9QAAeoBoADQaNAADQ09IAACSSGUwaJpTNQGE9QZGhoADQPUAA0AAA
AA0aA4AAAABoAAAAA0GgAAAAZAGgAHAAAAANAAAAAGg0AAAADIA0AASJCBIyE8hHpqPVPUPU/VAa
fqn6o0ep6BB6TQaNGj0j1ABobU00yeU9JYiuVVZKYE+dKNa3wls6x81yBpGAN71NoylDUvNryWiW
E4ER8XkfpaJcPb6ND12ULEqkQX3eaBHP70Apa5uFhWNDy+U3Ekj+OLx5MtDHxQHQLfMcgCHrGayE
Dc76F4ZC4rcRkvTW4S2EbJAsbBGbQxSbx5o48zkyk5iPBBhJowtCSwDBsQBc0koYRSO6SgJNL0Bg
EmCoxCDAs5QkEmTGmQUgqZNIoxsmwDmDQe0NIDI0KjQ64leOr1fVk6AaVhjOAJjLrEYkYy4cDbyS
iXSuILWohNh+PA9Izk0YUM4TQQGEYNgn4oEjGmAByO+kzmDIxEC3Txni6E1WdswBJLKYiANdiQ2K
00jU/zpMzuIhjTbgiBqE24dZWBcNBBAAioiEhCQEIfAR8Vir4zNQZFgvKZa67Jckh6EHZWAWuf6Q
kGy1lOtA2h9fsyD/uPPI2kjvoYL+w54IUKBEEYFBIWRNCNpuyY86v3pNiHEB7XyCX5wDjZUSF2tO
w0PVlY2FQNcLQcbZjmMhZdlCGkVHojuICHMMMB5kQQSZRwNJkYTKz6stT/MTWmozDCcj+UjtB9Cf
CUqAqqRlgJdREtMtSO4S4GpJE2I/P8vuO9ckqCM2+iSJCLRWx2Gi8VSR8BIkVX6stqIDmtG8xSVU
kk7BnC5caZXTIynyI0doXiFY1+/Csw2RUQJroC0lCNiIqVVUkTqTRMYqKNVGtCJ5yfo7e3ZpgECk
PYUEihPU0QVgfQ76JA8Eb16KCbSzP3WYiVApqmfDhUk0aVc+jyBJH13uKztUuva8F4YdbpmzomjG
kSJmP+vCFdKkHU384LdRoO0LdN7VJlywJ2xJdM+TMQ0KhMaicvRqfC5pHSu+gVDVjfiss+S00ikI
DeMgatVKKtcjsVDX09XU3SzowLWXXunnFZp/fP3eN9Rj1ubiLc0utMl3CUUkcYsmwbKKrWhaZiLO
u67kMSsW20jVBcZ5tZUKgdRtu0UleWOs1HK2QdMpyKMxTRHWhhHwMnVEsWIUEjIfFEbWhRTRMJXn
oIBSEa2Q0llTBfJV0LEYEQTBTFsDKIxhgqNwZB2dovl/kiW4TLp6aGXxmoIpVeWTEXqg1PnyKwux
caORGyBhTEPV2G7/O3y+KeAL9mUM4Zjl1DsDKyTZy8vgn31EDY08rY+64Z/LO5tcRJHttMYsz0Fh
CRN8LTYJL/I/4u5IpwoSCtDViIA=
EOF
更新:
ld.gold
时而不是
ld.bfd
(默认情况下,
/usr/bin/ld
被符号链接(symbolic link)到),可执行文件大小变得与预期一样小:
$ cat Makefile
TARGET=helloworld
all:
as -32 -o ${TARGET}-asm.o ${TARGET}-asm.s
ld.bfd -melf_i386 -o ${TARGET}-asm-bfd ${TARGET}-asm.o
ld.gold -melf_i386 -o ${TARGET}-asm-gold ${TARGET}-asm.o
rm ${TARGET}-asm.o
$ make -q
$ ls -l
total 68
-rw-r--r-- 1 eso eso 200 Dec 1 13:57 Makefile
-rwxrwxr-x 1 eso eso 8700 Dec 1 13:57 helloworld-asm-bfd
-rwxrwxr-x 1 eso eso 732 Dec 1 13:57 helloworld-asm-gold
-rw-r--r-- 1 eso eso 498 Dec 1 13:44 helloworld-asm.s
也许我只是用了
gold
之前不知不觉。
最佳答案
一般来说,它不是 10 倍,它是 Jester 所说的几个部分的页面对齐,根据对 ld
的更改出于安全原因的默认链接描述文件:
.data
的数据不存在于 .text
的任何映射中,因此这些静态数据都不适用于可执行页面中的 ROP/Spectre 小工具。 (在较早的 ld
中,这意味着程序头两次映射相同的磁盘 block ,也映射到实际 .data 部分的 RW-without-exec 段。可执行映射仍然是只读的。).rodata
来自 .text
分成单独的段,因此静态数据不会映射到可执行页面中。以前,const char code[]= {...}
可以转换为函数指针并调用,而不需要 mprotect 或 gcc -z execstack
或其他技巧,如果你想 test shellcode那样。 (一个单独的 Linux 内核更改 -z execstack
仅适用于实际堆栈,不适用于 READ_IMPLIES_EXEC。).rodata
的奇怪事实位于与只读映射不同的段中,用于访问 ELF 元数据。00
填充并将在
.tar.gz
中很好地压缩管他呢。
gcc -Wl,--nmagic
如果出于某种原因需要,将关闭部分的页面对齐。 (见
ld(1)
man page )我不知道为什么不能把所有东西都打包到旧尺寸。也许检查默认的链接器脚本会有所帮助,但它很长。运行
ld --verbose
看见了。
strip
ping 对作为部分一部分的填充没有帮助;我认为它只能删除整个部分。
ld -z noseparate-code
使用旧布局,总共只有 2 个段来覆盖
.text
和
.rodata
部分,以及
.data
和
.bss
部分。 (以及动态链接想要访问的 ELF 元数据。)
gcc
链接而不是
ld
这个问题是关于
ld
,但请注意,如果您使用的是
gcc -nostdlib
,过去也默认制作静态可执行文件。但是现代 Linux 发行版使用
-pie
配置 GCC作为默认值,GCC
won't make a static-pie by default即使没有链接任何共享库。与
-no-pie
不同在这种情况下,它将简单地生成静态可执行文件的模式。 (
static-pie 仍然需要启动代码来为任何绝对地址应用重定位。)
ld
直接是
gcc -nostdlib -static
(这意味着
-no-pie
)。或
gcc -nostdlib -no-pie
应该让它默认为
-static
当没有链接共享库时。您可以将其与
-Wl,--nmagic
结合使用和/或
-Wl,-z -Wl,noseparate-code
.
_exit
系统调用填充到 ELF 程序头本身。关于linux - 对于微型程序,链接后最小的可执行文件大小现在比 2 年前大 10 倍?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65037919/
考虑开始日期和结束日期: NSDate *startDate, *endDate; 例如,开始日期可以是 2010 年 12 月 10 日,结束日期可以是 2011 年 1 月 4 日。 考虑从 20
我试图将 maxdate 值设置为 18 年前,但我做不到。 setMaxDate(new Date().getTime()-18*365*24*60*60*1000); 我正在使用上面的方法,我只想
HTML: JS: var maxBirthdayDate = new Date(); maxBirthdayDate.setFullYear( maxBirthdayDate.getFullYea
我正在使用此代码在 android 中生成日期选择器。 DatePickerDialog datePicker = new DatePickerDialog(this, datePickerListe
我想将选择器 View 的默认日期设置为从当前日期往前 10 年。到目前为止,我的代码是这样的。 let datePicker = UIDatePicker() da
我试图让我的jquery日期选择器默认在过去18年打开(用户必须年满18岁才能使用应用程序),并且我不希望他们能够选择任何不存在的日期t 过去 18 年或以上。我有这段代码,但除了显示默认的今天日期之
我正在尝试将日期转换为过去时间。返回的内容:1 小时前、1 个月前、2 个月前、1 年前。 这是一个从 WordPress 获取博客文章的 Android 应用程序。 但是,我当前的代码返回(对于每个
我正在使用https://github.com/ChiperSoft/Kalendae这是一个基于JS的日期选择器。 我想知道是否可以将 Kalendae 当前月份/日期设置为 17 年前 + 从那时
我试图从我的数据库中获取早于 1 年的所有记录的列表,expired_contract 字段有下一个信息。 expired_contract DATE NOT NULL 所以它采用下一种格式的 DAT
我正在尝试查询超过 5 年的机器计数。 我的机器数据位于一个选项卡中,K 列中包含日期时间戳,例如“8/8/2008 8:08:08” 我尝试了许多不同的变体来获得正确的查询...但我最新的是这样的
我如何回到去年的 4 月 4 日(从今天开始),减去 4 年,然后返回那个日期? 我可以先检查今天的日期是在今年 4 月 4 日之前还是之后,然后从那里开始,但我很想看看解决这个问题的不同方法。 这将
我尝试在运行 Spring Boot 2.3.0 的 maven 项目中使用 buildpack: mvn spring-boot:build-image 图像创建得很好,但我看到了以下信息: REP
我是一名优秀的程序员,十分优秀!