__int128类型movaps指令crash

结论

在使用__int128时,如果__int128类型的内存起始地址不是按16字节对齐的话,有些汇编指令会抛出SIGSEGV使程序crash。

malloc在64位系统中申请的内存地址,是按16字节对齐的,但一般使用时经常会申请一块内存自己切割使用,往往会忽略一些类型的对齐。

案例

目前知道的两个指令是msse指令集的movaps和vmovaps,都是用来给int128赋值的,例如下面两种场景:

  1. (访问rax+0x30地址即 0x328dba8 + 0x30 = 0x328dbd8,对齐8字节,但没对齐16字节)
  2. (访问rax+0x30地址即 0x2d20b48 + 0x20 = 0x2d20b68,对齐8字节,但没对齐16字节)

复现

#include <stdio.h>

// gcc -g -O2 -Wall -msse4.2 -o test test.c

// core
typedef unsigned __int128 uint128;

// no core
// typedef unsigned __int128 uint128 __attribute__((aligned(8)));

static char mem[100];

typedef struct MySt
{
	int a;
	uint128 i;
	int b;
} MySt;

int main(void)
{
	MySt *st = (MySt *)(mem + 1);
	printf("st = %p\n", st);
	printf("st->i = %p\n", &st->i);
	__int128 tmp = 123123;
	st->a = 0;
	st->i = tmp * 123;
	st->b = 0;
	st = st;
	return st->i + 1 == 123;
}

gcc -g -O2 -Wall -msse4.2 -o test test.c可复现(不同的机器、编译器版本有不同的效果,可以看下编出来的二进制有无movaps指令,如果都是mov肯定没问题)。

相关推荐
桃酥4036 天前
GCC实用干货
linux·shell·gcc
张一西12 天前
ARM学习(35)单元测试框架以及MinGW GCC覆盖率报告
单元测试·mingw·gcc·覆盖率·cppunit·gcov
时光の尘13 天前
Linux进阶·如何在Ubuntu安装、调试、运行gcc/g++,以及如何进行多文件编译
linux·运维·服务器·c语言·c++·ubuntu·gcc
凛冬将至__1 个月前
【GNU】gcc -g编译选项 -g0 -g1 -g2 -g3 -gdwarf
linux·gnu·gcc
一丝晨光1 个月前
gcc 1.c和g++ 1.c编译阶段有什么区别?如何知道g++编译默认会定义_GNU_SOURCE?
c语言·开发语言·c++·gnu·clang·gcc·g++
一只特立独行的程序猿1 个月前
关于GCC内联汇编(也可以叫内嵌汇编)的简单学习
汇编·学习·gcc
一丝晨光1 个月前
编译器、IDE对C/C++新标准的支持
c语言·开发语言·c++·ide·msvc·visual studio·gcc
一丝晨光1 个月前
GCC和clang的爱恨情仇
macos·objective-c·xcode·apple·clang·gcc·llvm
云中双月2 个月前
如何使用Ida Pro和Core Dump文件定位崩溃位置(Linux下无调试符号的进程专享)
linux·嵌入式·gdb·调试·gcc·崩溃·ida pro·ulimit·core dump·cross compile
witton2 个月前
C语言实现Go的defer功能
c语言·clang·gcc·defer·attribute·cleanup·block type