C 不再是一种编程语言( 五 )


而事实上,微软实际上有理由使用这种版本方案,并定义了两个版本的数组元素:
typedef struct _MINIDUMP_HANDLE_DESCRIPTOR { ULONG64 Handle; RVA TypeNameRva; RVA ObjectNameRva; ULONG32 Attributes; ULONG32 GrantedAccess; ULONG32 HandleCount; ULONG32 PointerCount;} MINIDUMP_HANDLE_DESCRIPTOR, *PMINIDUMP_HANDLE_DESCRIPTOR;typedef struct _MINIDUMP_HANDLE_DESCRIPTOR_2 { ULONG64 Handle; RVA TypeNameRva; RVA ObjectNameRva; ULONG32 Attributes; ULONG32 GrantedAccess; ULONG32 HandleCount; ULONG32 PointerCount; RVA ObjectInfoRva; ULONG32 Reserved0;} MINIDUMP_HANDLE_DESCRIPTOR_2, *PMINIDUMP_HANDLE_DESCRIPTOR_2;// The latest MINIDUMP_HANDLE_DESCRIPTOR definition.typedef MINIDUMP_HANDLE_DESCRIPTOR_2 MINIDUMP_HANDLE_DESCRIPTOR_N;typedef MINIDUMP_HANDLE_DESCRIPTOR_N *PMINIDUMP_HANDLE_DESCRIPTOR_N;这些结构的实际细节不是很有趣,除了:

  • 他们只是通过在末尾添加字段来改变它
  • 有一个“最新版本”的类型定义
  • 保留了一些也许再次Padding(填充)(RVA是一个ULONG32)
这是一个坚不可摧的向前兼容的庞然大物 。它们对填充非常小心,它甚至在32位和64位之间有相同的布局 (这实际上是非常重要的,因为你希望一个架构上的minidump处理器能够处理来自每个架构的minidump) 。
C 不再是一种编程语言

文章插图
案例研究:jmp_buf
Aria对这种情况不是很熟悉,但在研究历史上的glibc中断时,她在LWN上看到了一篇很棒的文章:《glibc s390 ABI中断》,她假设它是准确的 。
事实证明,glibc曾经破解过类型的ABI,至少在s390上 。根据这篇文章的描述,它是混乱的 。
特别是他们改变了setjmp/longjmp使用的保存状态类型的布局,即jmp_buf 。现在,他们知道这是一个破坏ABI的变化,所以他们做了负责任的符号版本化的事情 。
jmp_buf并不是一个不透明的类型,其他东西都在内联地存储这个类型的实例,比如Perl的运行时间 。不用说,这个相对晦涩的类型已经渗透到许多二进制文件中去了,最终的结论是,Debian的所有东西都需要重新编译!
这篇文章甚至讨论了将libc版本升级以应对这种情况的可能性:
在像debian这样的混合ABI环境中,SO名称碰撞导致两个libc被加载并争夺相同的符号命名空间,而解析(以及因此选择ABI)则由ELF插值和范围规则决定 。这真是一场噩梦 。这可能是一个比告诉大家重建并继续生活更糟糕的解决方案 。

C 不再是一种编程语言

文章插图
真的能改变intmax_t吗?
在Aria看来,不完全是 。就像jmp_buf一样,它不是一个不透明的类型,这意味着它被内联到大量的随机结构中,被认为具有大量其他语言和编译器的特定表示,并且可能是大量公共接口的一部分 。而这些接口并不在libc、Linux,甚至不在发行版维护者的控制之下 。
当然,libc可以适当地使用符号版本技巧来使其API与新的定义兼容,但改变像 intmax_t这样的基本数据类型的大小,是在一个平台的大生态系统中寻求混乱 。
Aria希望被证明自己是错误的,但据她所知,做出这样的改变需要一个新的目标三元组,并且不允许任何为旧ABI构建的二进制/库在这个新三元组上运行 。当然有人可以做这些工作,但Aria并不羡慕任何这样做的发行版 。
即使如此,面临的还有x64的int问题:这是一个非常基本的类型,而且长期以来一直是这种大小,无数的应用程序可能对它有奇怪的无法察觉的假设 。这就是为什么int在x64上是32位的,尽管它应该是64位的:int是32位的时间太长了,以至于完全无望将软件更新到新的大小,尽管它是一个全新的架构和目标三元组 。
Aria再次希望自己是错的,但是人们有时犯的错误如此严重,以至于根本无法挽回 。如果C语言是一种独立的编程语言?当然可以去做 。但它不是,它是一个协议,还是我们必须使用的糟糕的协议 。
就算C征服了世界,但也许它再也得不到好东西了 。

【C 不再是一种编程语言】


推荐阅读