Forwarded from duangsues.is_a? SaltedFish
绿色化,后台纯净
语法规范
主要是程序自动cocel
不然很容易导致内存溢出
我这个手机就已经溢出了
没溢出的时候玩游戏贼流畅
现在溢出了,聊QQ都卡出翔
#然后我就怼了几句
所以我突然在思考
内存溢出是啥
is that edible?
JVM 应用有啥典型的溢出情况
Python 呢
#小白回
语法不规范导致的进程不在运行后所申请的内存仍然被使用
RefCount GC 为什么不能清理循环引用导致内存溢出
循环引用是什么
为什么我们需要 JVM 使用 CMS 而不是快速优雅简单的 Rc(滑稽问号)
因为我们需要循环引用
class A {
B b;
public A(B bb) { b = bb; }
}
class B {
public A a;
public B() {}
}
B bb = new B();
A aa = new A(bb);
bb.a = aa;
语法规范
主要是程序自动cocel
不然很容易导致内存溢出
我这个手机就已经溢出了
没溢出的时候玩游戏贼流畅
现在溢出了,聊QQ都卡出翔
#然后我就怼了几句
所以我突然在思考
内存溢出是啥
is that edible?
JVM 应用有啥典型的溢出情况
Python 呢
#小白回
语法不规范导致的进程不在运行后所申请的内存仍然被使用
RefCount GC 为什么不能清理循环引用导致内存溢出
循环引用是什么
为什么我们需要 JVM 使用 CMS 而不是快速优雅简单的 Rc(滑稽问号)
因为我们需要循环引用
class A {
B b;
public A(B bb) { b = bb; }
}
class B {
public A a;
public B() {}
}
B bb = new B();
A aa = new A(bb);
bb.a = aa;
Forwarded from duangsues.is_a? SaltedFish
This media is not supported in your browser
VIEW IN TELEGRAM
Forwarded from duangsues.is_a? SaltedFish
说实话,其实我也不是大佬。但看到这种菜还特别自以为是的就非常想讽刺一下
duangsues.is_a? SaltedFish
说实话,其实我也不是大佬。但看到这种菜还特别自以为是的就非常想讽刺一下
#PL #Lowlvl_backend 看了一点帖子后科普一下
另外上面数组下标越界是一种情况,stackoverflow 也是一种溢出
内存溢出容易和分配失败混淆
内存溢出就是内存越界#include <stdio.h>
int main(int argc, char **argv) {
int ary[2] = {233, 666};
printf("%i, %i, %i, %i\n", ary[0], ary[1], ary[-1], ary[2]);
}
dse@susepc:~$ clang -Wall -Wextra b.c -o bbb
b.c:3:14: warning: unused parameter 'argc' [-Wunused-parameter]
int main(int argc, char **argv) {
^
b.c:3:27: warning: unused parameter 'argv' [-Wunused-parameter]
int main(int argc, char **argv) {
^
b.c:5:46: warning: array index -1 is before the beginning of the array [-Warray-bounds]
printf("%i, %i, %i, %i\n", ary[0], ary[1], ary[-1], ary[2]);
^ ~~
b.c:4:3: note: array 'ary' declared here
int ary[2] = {233, 666};
^
b.c:5:55: warning: array index 2 is past the end of the array (which contains 2 elements) [-Warray-bounds]
printf("%i, %i, %i, %i\n", ary[0], ary[1], ary[-1], ary[2]);
^ ~
b.c:4:3: note: array 'ary' declared here
int ary[2] = {233, 666};
^
4 warnings generated.
dse@susepc:~$ ./bbb
233, 666, 0, 1936233432
另外上面数组下标越界是一种情况,stackoverflow 也是一种溢出
内存溢出容易和分配失败混淆
duangsuse::Echo
#PL #Lowlvl_backend 看了一点帖子后科普一下 内存溢出就是内存越界 #include <stdio.h> int main(int argc, char **argv) { int ary[2] = {233, 666}; printf("%i, %i, %i, %i\n", ary[0], ary[1], ary[-1], ary[2]); } dse@susepc:~$ clang -Wall -Wextra b.c -o bbb b.c:3:14: warning: unused…
因为我开了
ASLR 并且没法关闭(估计是新版本 Linux 强制使用),所以没办法重现主要越界访问导致的问题下面是明显一点的:
测试
nasm b.s -f elf64 -o bbb; chmod +x bbb; ld bbb -lc -Bdynamic -I/lib64/ld-linux-x86-64.so.2 -o bb
./bb
然后一直段错误不想开调试器了
于是我就换成内联 assembly
然后打开 edb 调试了一下结合 plasm disasm 认为还是 fmt 有问题
累死还没写完
(WASM 是堆栈机方便
测试
extern printf
section .text
global _start
_start:
push fmt
push 0
call printf
leave
ret
section .data
fmt: db '%i', 0
nasm b.s -f elf64 -o bbb; chmod +x bbb; ld bbb -lc -Bdynamic -I/lib64/ld-linux-x86-64.so.2 -o bb
./bb
然后一直段错误不想开调试器了
于是我就换成内联 assembly
#include <stdio.h>
void prints() {
char fmt[3] = "%i";
asm volatile (
"push %0\n\t"
"push $0\n\t"
"call printf"
: "=r" (fmt)
);
}
int main(int argc, char **argv) {
//printf("%i", 0);
prints();
return 0;
}
然后打开 edb 调试了一下结合 plasm disasm 认为还是 fmt 有问题
累死还没写完
(WASM 是堆栈机方便
#Learn #Lowlvl_backend #sysadmin #android
在学会手动使用 GCC 工具链链接 native ELF 对象文件后 duangsuse 也终于知道为什么在
科普一下,曾经在手机上遇到过的
首先我们有一个
clang a.c -fno-stack-protector -std=c99 -o hello -Xlinker —verbose | grep found
然后我们就获得了一个输出的 ELF 可执行文件
file hello
./hello
接下来就是魔改链接器 ld 参数的时候了,首先我们先准备好 helloworld 准备自己链接
clang a.c -c -fno-stack-protector -o hello -std=c99
file hello
链接!
file a.out
./a.out
???
明明有这个文件啊
然后我们尝试一下
OSError: ./a.out: cannot dynamically load executable
🌚 无法加载(因为亲定的解释器不存在)
那如果尝试加载一个不存在的文件呢
OSError: ./foo: cannot open shared object file: No such file or directory
那么我们用 elvish.io 再尝试一下,到底彻底找不到和这种「找不到」有啥区别
那么问题就解决了吗,你为
可是到了
当然找不到解释器无法加载了.... 🙈
ps. 这里默认测试是在 x86_64 架构的 Android 上进行的
补充:
找不到的解释器
所以我刚才正好编译完了一个 edb 顺便来看看
edb:
在学会手动使用 GCC 工具链链接 native ELF 对象文件后 duangsuse 也终于知道为什么在
./a.out 的时候 bash 会在明明有文件的时候说找不到文件科普一下,曾经在手机上遇到过的
首先我们有一个
Hello, world! C 程序的代码#include <stdio.h>
int main(int argc, char **argv) {
printf("Hello, world!!!\n");
}
clang a.c -fno-stack-protector -std=c99 -o hello -Xlinker —verbose | grep found
found ld-linux-x86-64.so.2 at /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2然后我们就获得了一个输出的 ELF 可执行文件
hellofile hello
hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, not stripped./hello
Hello, world!!!接下来就是魔改链接器 ld 参数的时候了,首先我们先准备好 helloworld 准备自己链接
clang a.c -c -fno-stack-protector -o hello -std=c99
file hello
hello: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped链接!
dlinker=foo #/lib64/ld-linux-x86-64.so.2
ld -lc -m elf_x86_64 -dynamic-linker $dlinker -o a.out /usr/bin/../lib/gcc/x86_64-linux-gnu/7.3.0/../../../x86_64-linux-gnu/crt1.o /usr/bin/../lib/gcc/x86_64-linux-gnu/7.3.0/../../../x86_64-linux-gnu/crti.o /usr/bin/../lib/gcc/x86_64-linux-gnu/7.3.0/crtbegin.o -L/usr/bin/../lib/gcc/x86_64-linux-gnu/7.3.0 -L/usr/bin/../lib/gcc/x86_64-linux-gnu/7.3.0/../../../x86_64-linux-gnu -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/bin/../lib/gcc/x86_64-linux-gnu/7.3.0/../../.. -L/usr/lib/llvm-4.0/bin/../lib -L/lib -L/usr/lib hello -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/bin/../lib/gcc/x86_64-linux-gnu/7.3.0/crtend.o /usr/bin/../lib/gcc/x86_64-linux-gnu/7.3.0/../../../x86_64-linux-gnu/crtn.o # 参数可从 clang hello --verbose 里抄
file a.out
a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter foo, for GNU/Linux 3.2.0, not stripped./a.out
bash: ./a.out: 没有那个文件或目录???
明明有这个文件啊
然后我们尝试一下
IPythonimport ctypes
ctypes.cdll.LoadLibrary('./a.out')
OSError: ./a.out: cannot dynamically load executable
🌚 无法加载(因为亲定的解释器不存在)
那如果尝试加载一个不存在的文件呢
ctypes.cdll.LoadLibrary('./foo')OSError: ./foo: cannot open shared object file: No such file or directory
那么我们用 elvish.io 再尝试一下,到底彻底找不到和这种「找不到」有啥区别
./a.out
Exception: fork/exec ./a.out: no such file or directory
./no_such_file
Exception: exec: "./no_such_file": stat ./no_such_file: no such file or directory
那么问题就解决了吗,你为
x86_64-pc-linux-gnu 编译的 ELF 可执行文件,默认使用 /lib64/ld-linux-x86-64.so.2 链接执行可是到了
Android 上默认动态链接器是 /system/bin/linker ,没有 /lib64/ld-linux-x86-64.so.2当然找不到解释器无法加载了.... 🙈
ps. 这里默认测试是在 x86_64 架构的 Android 上进行的
补充:
找不到的解释器
ldd 在我的垃圾 Debian x86_64 上默认使用 /lib64/ld-linux-x86-64.so.2 替代所以我刚才正好编译完了一个 edb 顺便来看看
edb:
Failed to open and attach to process:
execv() failed: 没有那个文件或目录.
^之后 duangsuse 自然套路
然后妄想可以正常运行了 🙈
echo "#!/lib64/ld-linux-x86-64.so.2\n" > fooocat a.out >> fooo然后妄想可以正常运行了 🙈
./fooo: error while loading shared libraries: ./fooo: invalid ELF header另外你们不要以为
/lib64/ld-linux-x86-64.so.2
ldd /lib64/ld-linux-x86-64.so.2
它当然是静态链接的。要不然就要发生无尽递归的情况了
/lib64/ld-linux-x86-64.so.2 是一个库,它是一个 CLI 工具(helper program),要不然怎么链接程序呢(删掉/lib64/ld-linux-x86-64.so.2
Usage: ld.so [OPTION]... EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]
You have invoked `ld.so', the helper program for shared library executables.
This program usually lives in the file `/lib/ld.so', and special directives
in executable files using ELF shared libraries tell the system's program
loader to load the helper program from this file. This helper program loads
the shared libraries needed by the program executable, prepares the program
to run, and runs it. You may invoke this helper program directly from the
command line to load and run an ELF executable file; this is like executing
that file itself, but always uses this helper program from the file you
specified, instead of the helper program file specified in the executable
file you run. This is mostly of use for maintainers to test new versions
of this helper program; chances are you did not intend to run this program.
--list list all dependencies and how they are resolved
--verify verify that given object really is a dynamically linked
object we can handle
--inhibit-cache Do not use /etc/ld.so.cache
--library-path PATH use given PATH instead of content of the environment
variable LD_LIBRARY_PATH
--inhibit-rpath LIST ignore RUNPATH and RPATH information in object names
in LIST
--audit LIST use objects named in LIST as auditors
ldd /lib64/ld-linux-x86-64.so.2
statically linked它当然是静态链接的。要不然就要发生无尽递归的情况了