UP | HOME

The Mess We Are In

This is a sort of a tribute to Joe Armstrong.

#include <iostream>

int main() { std::cout << "Hello, World!" << std::endl; }
clang++ -m64 -march=native -std=c++20 -stdlib=libc++ -O3 a.cpp
ldd ./a.out
	linux-vdso.so.1 (0x00007ffc46ed5000)
	libc++.so.1 => /usr/lib64/libc++.so.1 (0x00007fa8c2449000)
	libc++abi.so.1 => /usr/lib64/libc++abi.so.1 (0x00007fa8c2405000)
	libunwind.so.8 => /usr/lib64/libunwind.so.8 (0x00007fa8c23e7000)
	libm.so.6 => /lib64/libm.so.6 (0x00007fa8c230d000)
	libc.so.6 => /lib64/libc.so.6 (0x00007fa8c2136000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fa8c257e000)
	liblzma.so.5 => /lib64/liblzma.so.5 (0x00007fa8c20ff000)

Gentoo uses the wrong libunwind, but it does not matter.

objdump -d a.out
a.out:	file format elf64-x86-64

Disassembly of section .text:

0000000000001ed0 <_start>:
    1ed0: f3 0f 1e fa                  	endbr64
    1ed4: 31 ed                        	xorl	%ebp, %ebp
    1ed6: 49 89 d1                     	movq	%rdx, %r9
    1ed9: 5e                           	popq	%rsi
    1eda: 48 89 e2                     	movq	%rsp, %rdx
    1edd: 48 83 e4 f0                  	andq	$-16, %rsp
    1ee1: 50                           	pushq	%rax
    1ee2: 54                           	pushq	%rsp
    1ee3: 45 31 c0                     	xorl	%r8d, %r8d
    1ee6: 31 c9                        	xorl	%ecx, %ecx
    1ee8: 48 8d 3d 81 00 00 00         	leaq	129(%rip), %rdi         # 0x1f70 <main>
    1eef: ff 15 db 17 00 00            	callq	*6107(%rip)             # 0x36d0 <memset+0x36d0>
    1ef5: f4                           	hlt
    1ef6: cc                           	int3
    1ef7: cc                           	int3
    1ef8: cc                           	int3
    1ef9: cc                           	int3
    1efa: cc                           	int3
    1efb: cc                           	int3
    1efc: cc                           	int3
    1efd: cc                           	int3
    1efe: cc                           	int3
    1eff: cc                           	int3
    1f00: 80 3d d1 28 00 00 00         	cmpb	$0, 10449(%rip)         # 0x47d8 <memset+0x47d8>
    1f07: 75 24                        	jne	0x1f2d <_start+0x5d>
    1f09: c6 05 c8 28 00 00 01         	movb	$1, 10440(%rip)         # 0x47d8 <memset+0x47d8>
    1f10: 48 83 3d c8 17 00 00 00      	cmpq	$0, 6088(%rip)          # 0x36e0 <memset+0x36e0>
    1f18: 74 13                        	je	0x1f2d <_start+0x5d>
    1f1a: 48 8d 3d 3f ee ff ff         	leaq	-4545(%rip), %rdi       # 0xd60 <__EH_FRAME_LIST_END__>
    1f21: 48 8d 35 b8 28 00 00         	leaq	10424(%rip), %rsi       # 0x47e0 <memset+0x47e0>
    1f28: e9 63 04 00 00               	jmp	0x2390 <__register_frame_info@plt>
    1f2d: c3                           	retq
    1f2e: 66 90                        	nop
    1f30: 50                           	pushq	%rax
    1f31: 80 3d e8 28 00 00 00         	cmpb	$0, 10472(%rip)         # 0x4820 <memset+0x4820>
    1f38: 75 34                        	jne	0x1f6e <_start+0x9e>
    1f3a: c6 05 df 28 00 00 01         	movb	$1, 10463(%rip)         # 0x4820 <memset+0x4820>
    1f41: 48 83 3d 9f 17 00 00 00      	cmpq	$0, 6047(%rip)          # 0x36e8 <memset+0x36e8>
    1f49: 74 0c                        	je	0x1f57 <_start+0x87>
    1f4b: 48 8b 3d be 27 00 00         	movq	10174(%rip), %rdi       # 0x4710 <__dso_handle>
    1f52: e8 49 04 00 00               	callq	0x23a0 <__cxa_finalize@plt>
    1f57: 48 83 3d 91 17 00 00 00      	cmpq	$0, 6033(%rip)          # 0x36f0 <memset+0x36f0>
    1f5f: 74 0d                        	je	0x1f6e <_start+0x9e>
    1f61: 48 8d 3d f8 ed ff ff         	leaq	-4616(%rip), %rdi       # 0xd60 <__EH_FRAME_LIST_END__>
    1f68: 58                           	popq	%rax
    1f69: e9 42 04 00 00               	jmp	0x23b0 <__deregister_frame_info@plt>
    1f6e: 58                           	popq	%rax
    1f6f: c3                           	retq

0000000000001f70 <main>:
    1f70: 55                           	pushq	%rbp
    1f71: 53                           	pushq	%rbx
    1f72: 48 83 ec 18                  	subq	$24, %rsp
    1f76: 64 48 8b 04 25 28 00 00 00   	movq	%fs:40, %rax
    1f7f: 48 89 44 24 10               	movq	%rax, 16(%rsp)
    1f84: 48 8b 3d 6d 17 00 00         	movq	5997(%rip), %rdi        # 0x36f8 <memset+0x36f8>
    1f8b: 48 8d 35 12 ed ff ff         	leaq	-4846(%rip), %rsi       # 0xca4 <_IO_stdin_used+0x4>
    1f92: ba 0d 00 00 00               	movl	$13, %edx
    1f97: e8 94 00 00 00               	callq	0x2030 <_ZNSt3__124__put_character_sequenceIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_m>
    1f9c: 48 89 c3                     	movq	%rax, %rbx
    1f9f: 48 8b 00                     	movq	(%rax), %rax
    1fa2: 48 8b 70 e8                  	movq	-24(%rax), %rsi
    1fa6: 48 01 de                     	addq	%rbx, %rsi
    1fa9: 48 8d 6c 24 08               	leaq	8(%rsp), %rbp
    1fae: 48 89 ef                     	movq	%rbp, %rdi
    1fb1: e8 0a 04 00 00               	callq	0x23c0 <_ZNKSt3__18ios_base6getlocEv@plt>
    1fb6: 48 8b 35 43 17 00 00         	movq	5955(%rip), %rsi        # 0x3700 <memset+0x3700>
    1fbd: 48 89 ef                     	movq	%rbp, %rdi
    1fc0: e8 0b 04 00 00               	callq	0x23d0 <_ZNKSt3__16locale9use_facetERNS0_2idE@plt>
    1fc5: 48 8b 08                     	movq	(%rax), %rcx
    1fc8: 48 89 c7                     	movq	%rax, %rdi
    1fcb: be 0a 00 00 00               	movl	$10, %esi
    1fd0: ff 51 38                     	callq	*56(%rcx)
    1fd3: 89 c5                        	movl	%eax, %ebp
    1fd5: 48 8d 7c 24 08               	leaq	8(%rsp), %rdi
    1fda: e8 01 04 00 00               	callq	0x23e0 <_ZNSt3__16localeD1Ev@plt>
    1fdf: 40 0f be f5                  	movsbl	%bpl, %esi
    1fe3: 48 89 df                     	movq	%rbx, %rdi
    1fe6: e8 05 04 00 00               	callq	0x23f0 <_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE3putEc@plt>
    1feb: 48 89 df                     	movq	%rbx, %rdi
    1fee: e8 0d 04 00 00               	callq	0x2400 <_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE5flushEv@plt>
    1ff3: 64 48 8b 04 25 28 00 00 00   	movq	%fs:40, %rax
    1ffc: 48 3b 44 24 10               	cmpq	16(%rsp), %rax
    2001: 75 09                        	jne	0x200c <main+0x9c>
    2003: 31 c0                        	xorl	%eax, %eax
    2005: 48 83 c4 18                  	addq	$24, %rsp
    2009: 5b                           	popq	%rbx
    200a: 5d                           	popq	%rbp
    200b: c3                           	retq
    200c: e8 ff 03 00 00               	callq	0x2410 <__stack_chk_fail@plt>
    2011: 48 89 c3                     	movq	%rax, %rbx
    2014: 48 8d 7c 24 08               	leaq	8(%rsp), %rdi
    2019: e8 c2 03 00 00               	callq	0x23e0 <_ZNSt3__16localeD1Ev@plt>
    201e: 48 89 df                     	movq	%rbx, %rdi
    2021: e8 fa 03 00 00               	callq	0x2420 <_Unwind_Resume@plt>
    2026: cc                           	int3
    2027: cc                           	int3
    2028: cc                           	int3
    2029: cc                           	int3
    202a: cc                           	int3
    202b: cc                           	int3
    202c: cc                           	int3
    202d: cc                           	int3
    202e: cc                           	int3
    202f: cc                           	int3

0000000000002030 <_ZNSt3__124__put_character_sequenceIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_m>:
    2030: 55                           	pushq	%rbp
    2031: 41 57                        	pushq	%r15
    2033: 41 56                        	pushq	%r14
    2035: 41 55                        	pushq	%r13
    2037: 41 54                        	pushq	%r12
    2039: 53                           	pushq	%rbx
    203a: 48 83 ec 28                  	subq	$40, %rsp
    203e: 49 89 d6                     	movq	%rdx, %r14
    2041: 49 89 f7                     	movq	%rsi, %r15
    2044: 48 89 fb                     	movq	%rdi, %rbx
    2047: 64 48 8b 04 25 28 00 00 00   	movq	%fs:40, %rax
    2050: 48 89 44 24 20               	movq	%rax, 32(%rsp)
    2055: 48 8d 7c 24 08               	leaq	8(%rsp), %rdi
    205a: 48 89 de                     	movq	%rbx, %rsi
    205d: e8 ce 03 00 00               	callq	0x2430 <_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE6sentryC1ERS3_@plt>
    2062: 80 7c 24 08 00               	cmpb	$0, 8(%rsp)
    2067: 0f 84 ab 00 00 00            	je	0x2118 <_ZNSt3__124__put_character_sequenceIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_m+0xe8>
    206d: 48 8b 03                     	movq	(%rbx), %rax
    2070: 48 8b 40 e8                  	movq	-24(%rax), %rax
    2074: 4c 8d 24 03                  	leaq	(%rbx,%rax), %r12
    2078: 4c 8b 6c 03 28               	movq	40(%rbx,%rax), %r13
    207d: 8b 6c 03 08                  	movl	8(%rbx,%rax), %ebp
    2081: 8b 84 03 90 00 00 00         	movl	144(%rbx,%rax), %eax
    2088: 83 f8 ff                     	cmpl	$-1, %eax
    208b: 75 47                        	jne	0x20d4 <_ZNSt3__124__put_character_sequenceIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_m+0xa4>
    208d: 48 8d 7c 24 18               	leaq	24(%rsp), %rdi
    2092: 4c 89 e6                     	movq	%r12, %rsi
    2095: e8 26 03 00 00               	callq	0x23c0 <_ZNKSt3__18ios_base6getlocEv@plt>
    209a: 48 8b 35 5f 16 00 00         	movq	5727(%rip), %rsi        # 0x3700 <memset+0x3700>
    20a1: 48 8d 7c 24 18               	leaq	24(%rsp), %rdi
    20a6: e8 25 03 00 00               	callq	0x23d0 <_ZNKSt3__16locale9use_facetERNS0_2idE@plt>
    20ab: 48 8b 08                     	movq	(%rax), %rcx
    20ae: 48 89 c7                     	movq	%rax, %rdi
    20b1: be 20 00 00 00               	movl	$32, %esi
    20b6: ff 51 38                     	callq	*56(%rcx)
    20b9: 88 44 24 07                  	movb	%al, 7(%rsp)
    20bd: 48 8d 7c 24 18               	leaq	24(%rsp), %rdi
    20c2: e8 19 03 00 00               	callq	0x23e0 <_ZNSt3__16localeD1Ev@plt>
    20c7: 0f be 44 24 07               	movsbl	7(%rsp), %eax
    20cc: 41 89 84 24 90 00 00 00      	movl	%eax, 144(%r12)
    20d4: 81 e5 b0 00 00 00            	andl	$176, %ebp
    20da: 4d 01 fe                     	addq	%r15, %r14
    20dd: 83 fd 20                     	cmpl	$32, %ebp
    20e0: 4c 89 fa                     	movq	%r15, %rdx
    20e3: 49 0f 44 d6                  	cmoveq	%r14, %rdx
    20e7: 44 0f be c8                  	movsbl	%al, %r9d
    20eb: 4c 89 ef                     	movq	%r13, %rdi
    20ee: 4c 89 fe                     	movq	%r15, %rsi
    20f1: 4c 89 f1                     	movq	%r14, %rcx
    20f4: 4d 89 e0                     	movq	%r12, %r8
    20f7: e8 b4 00 00 00               	callq	0x21b0 <_ZNSt3__116__pad_and_outputIcNS_11char_traitsIcEEEENS_19ostreambuf_iteratorIT_T0_EES6_PKS4_S8_S8_RNS_8ios_baseES4_>
    20fc: 48 85 c0                     	testq	%rax, %rax
    20ff: 75 17                        	jne	0x2118 <_ZNSt3__124__put_character_sequenceIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_m+0xe8>
    2101: 48 8b 03                     	movq	(%rbx), %rax
    2104: 48 8b 40 e8                  	movq	-24(%rax), %rax
    2108: 48 8d 3c 03                  	leaq	(%rbx,%rax), %rdi
    210c: 8b 74 03 20                  	movl	32(%rbx,%rax), %esi
    2110: 83 ce 05                     	orl	$5, %esi
    2113: e8 28 03 00 00               	callq	0x2440 <_ZNSt3__18ios_base5clearEj@plt>
    2118: 48 8d 7c 24 08               	leaq	8(%rsp), %rdi
    211d: e8 2e 03 00 00               	callq	0x2450 <_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE6sentryD1Ev@plt>
    2122: 64 48 8b 04 25 28 00 00 00   	movq	%fs:40, %rax
    212b: 48 3b 44 24 20               	cmpq	32(%rsp), %rax
    2130: 75 61                        	jne	0x2193 <_ZNSt3__124__put_character_sequenceIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_m+0x163>
    2132: 48 89 d8                     	movq	%rbx, %rax
    2135: 48 83 c4 28                  	addq	$40, %rsp
    2139: 5b                           	popq	%rbx
    213a: 41 5c                        	popq	%r12
    213c: 41 5d                        	popq	%r13
    213e: 41 5e                        	popq	%r14
    2140: 41 5f                        	popq	%r15
    2142: 5d                           	popq	%rbp
    2143: c3                           	retq
    2144: eb 0f                        	jmp	0x2155 <_ZNSt3__124__put_character_sequenceIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_m+0x125>
    2146: 49 89 c6                     	movq	%rax, %r14
    2149: 48 8d 7c 24 18               	leaq	24(%rsp), %rdi
    214e: e8 8d 02 00 00               	callq	0x23e0 <_ZNSt3__16localeD1Ev@plt>
    2153: eb 03                        	jmp	0x2158 <_ZNSt3__124__put_character_sequenceIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_m+0x128>
    2155: 49 89 c6                     	movq	%rax, %r14
    2158: 48 8d 7c 24 08               	leaq	8(%rsp), %rdi
    215d: e8 ee 02 00 00               	callq	0x2450 <_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE6sentryD1Ev@plt>
    2162: eb 03                        	jmp	0x2167 <_ZNSt3__124__put_character_sequenceIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_m+0x137>
    2164: 49 89 c6                     	movq	%rax, %r14
    2167: 4c 89 f7                     	movq	%r14, %rdi
    216a: e8 f1 02 00 00               	callq	0x2460 <__cxa_begin_catch@plt>
    216f: 48 8b 03                     	movq	(%rbx), %rax
    2172: 48 8b 78 e8                  	movq	-24(%rax), %rdi
    2176: 48 01 df                     	addq	%rbx, %rdi
    2179: e8 f2 02 00 00               	callq	0x2470 <_ZNSt3__18ios_base33__set_badbit_and_consider_rethrowEv@plt>
    217e: e8 fd 02 00 00               	callq	0x2480 <__cxa_end_catch@plt>
    2183: 64 48 8b 04 25 28 00 00 00   	movq	%fs:40, %rax
    218c: 48 3b 44 24 20               	cmpq	32(%rsp), %rax
    2191: 74 9f                        	je	0x2132 <_ZNSt3__124__put_character_sequenceIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_m+0x102>
    2193: e8 78 02 00 00               	callq	0x2410 <__stack_chk_fail@plt>
    2198: 48 89 c3                     	movq	%rax, %rbx
    219b: e8 e0 02 00 00               	callq	0x2480 <__cxa_end_catch@plt>
    21a0: 48 89 df                     	movq	%rbx, %rdi
    21a3: e8 78 02 00 00               	callq	0x2420 <_Unwind_Resume@plt>
    21a8: 48 89 c7                     	movq	%rax, %rdi
    21ab: e8 90 01 00 00               	callq	0x2340 <__clang_call_terminate>

00000000000021b0 <_ZNSt3__116__pad_and_outputIcNS_11char_traitsIcEEEENS_19ostreambuf_iteratorIT_T0_EES6_PKS4_S8_S8_RNS_8ios_baseES4_>:
    21b0: 55                           	pushq	%rbp
    21b1: 41 57                        	pushq	%r15
    21b3: 41 56                        	pushq	%r14
    21b5: 41 55                        	pushq	%r13
    21b7: 41 54                        	pushq	%r12
    21b9: 53                           	pushq	%rbx
    21ba: 48 83 ec 38                  	subq	$56, %rsp
    21be: 64 48 8b 04 25 28 00 00 00   	movq	%fs:40, %rax
    21c7: 48 89 44 24 30               	movq	%rax, 48(%rsp)
    21cc: 48 85 ff                     	testq	%rdi, %rdi
    21cf: 0f 84 1c 01 00 00            	je	0x22f1 <_ZNSt3__116__pad_and_outputIcNS_11char_traitsIcEEEENS_19ostreambuf_iteratorIT_T0_EES6_PKS4_S8_S8_RNS_8ios_baseES4_+0x141>
    21d5: 4d 89 c6                     	movq	%r8, %r14
    21d8: 49 89 cf                     	movq	%rcx, %r15
    21db: 49 89 d4                     	movq	%rdx, %r12
    21de: 49 89 fd                     	movq	%rdi, %r13
    21e1: 44 89 4c 24 0c               	movl	%r9d, 12(%rsp)
    21e6: 48 89 c8                     	movq	%rcx, %rax
    21e9: 48 29 f0                     	subq	%rsi, %rax
    21ec: 49 8b 48 18                  	movq	24(%r8), %rcx
    21f0: 31 db                        	xorl	%ebx, %ebx
    21f2: 48 29 c1                     	subq	%rax, %rcx
    21f5: 48 0f 4f d9                  	cmovgq	%rcx, %rbx
    21f9: 48 89 d5                     	movq	%rdx, %rbp
    21fc: 48 29 f5                     	subq	%rsi, %rbp
    21ff: 48 85 ed                     	testq	%rbp, %rbp
    2202: 7e 16                        	jle	0x221a <_ZNSt3__116__pad_and_outputIcNS_11char_traitsIcEEEENS_19ostreambuf_iteratorIT_T0_EES6_PKS4_S8_S8_RNS_8ios_baseES4_+0x6a>
    2204: 49 8b 45 00                  	movq	(%r13), %rax
    2208: 4c 89 ef                     	movq	%r13, %rdi
    220b: 48 89 ea                     	movq	%rbp, %rdx
    220e: ff 50 60                     	callq	*96(%rax)
    2211: 48 39 e8                     	cmpq	%rbp, %rax
    2214: 0f 85 d7 00 00 00            	jne	0x22f1 <_ZNSt3__116__pad_and_outputIcNS_11char_traitsIcEEEENS_19ostreambuf_iteratorIT_T0_EES6_PKS4_S8_S8_RNS_8ios_baseES4_+0x141>
    221a: 48 85 db                     	testq	%rbx, %rbx
    221d: 0f 8e 94 00 00 00            	jle	0x22b7 <_ZNSt3__116__pad_and_outputIcNS_11char_traitsIcEEEENS_19ostreambuf_iteratorIT_T0_EES6_PKS4_S8_S8_RNS_8ios_baseES4_+0x107>
    2223: 4c 89 74 24 10               	movq	%r14, 16(%rsp)
    2228: 48 83 fb 17                  	cmpq	$23, %rbx
    222c: 73 0e                        	jae	0x223c <_ZNSt3__116__pad_and_outputIcNS_11char_traitsIcEEEENS_19ostreambuf_iteratorIT_T0_EES6_PKS4_S8_S8_RNS_8ios_baseES4_+0x8c>
    222e: 8d 04 1b                     	leal	(%rbx,%rbx), %eax
    2231: 88 44 24 18                  	movb	%al, 24(%rsp)
    2235: 4c 8d 74 24 19               	leaq	25(%rsp), %r14
    223a: eb 26                        	jmp	0x2262 <_ZNSt3__116__pad_and_outputIcNS_11char_traitsIcEEEENS_19ostreambuf_iteratorIT_T0_EES6_PKS4_S8_S8_RNS_8ios_baseES4_+0xb2>
    223c: 48 8d 6b 10                  	leaq	16(%rbx), %rbp
    2240: 48 83 e5 f0                  	andq	$-16, %rbp
    2244: 48 89 ef                     	movq	%rbp, %rdi
    2247: e8 44 02 00 00               	callq	0x2490 <_Znwm@plt>
    224c: 49 89 c6                     	movq	%rax, %r14
    224f: 48 89 44 24 28               	movq	%rax, 40(%rsp)
    2254: 48 83 cd 01                  	orq	$1, %rbp
    2258: 48 89 6c 24 18               	movq	%rbp, 24(%rsp)
    225d: 48 89 5c 24 20               	movq	%rbx, 32(%rsp)
    2262: 8b 44 24 0c                  	movl	12(%rsp), %eax
    2266: 0f b6 f0                     	movzbl	%al, %esi
    2269: 4c 89 f7                     	movq	%r14, %rdi
    226c: 48 89 da                     	movq	%rbx, %rdx
    226f: e8 2c 02 00 00               	callq	0x24a0 <memset@plt>
    2274: 41 c6 04 1e 00               	movb	$0, (%r14,%rbx)
    2279: f6 44 24 18 01               	testb	$1, 24(%rsp)
    227e: 74 07                        	je	0x2287 <_ZNSt3__116__pad_and_outputIcNS_11char_traitsIcEEEENS_19ostreambuf_iteratorIT_T0_EES6_PKS4_S8_S8_RNS_8ios_baseES4_+0xd7>
    2280: 48 8b 74 24 28               	movq	40(%rsp), %rsi
    2285: eb 05                        	jmp	0x228c <_ZNSt3__116__pad_and_outputIcNS_11char_traitsIcEEEENS_19ostreambuf_iteratorIT_T0_EES6_PKS4_S8_S8_RNS_8ios_baseES4_+0xdc>
    2287: 48 8d 74 24 19               	leaq	25(%rsp), %rsi
    228c: 4c 8b 74 24 10               	movq	16(%rsp), %r14
    2291: 49 8b 45 00                  	movq	(%r13), %rax
    2295: 4c 89 ef                     	movq	%r13, %rdi
    2298: 48 89 da                     	movq	%rbx, %rdx
    229b: ff 50 60                     	callq	*96(%rax)
    229e: 48 89 c5                     	movq	%rax, %rbp
    22a1: f6 44 24 18 01               	testb	$1, 24(%rsp)
    22a6: 74 0a                        	je	0x22b2 <_ZNSt3__116__pad_and_outputIcNS_11char_traitsIcEEEENS_19ostreambuf_iteratorIT_T0_EES6_PKS4_S8_S8_RNS_8ios_baseES4_+0x102>
    22a8: 48 8b 7c 24 28               	movq	40(%rsp), %rdi
    22ad: e8 fe 01 00 00               	callq	0x24b0 <_ZdlPv@plt>
    22b2: 48 39 dd                     	cmpq	%rbx, %rbp
    22b5: 75 3a                        	jne	0x22f1 <_ZNSt3__116__pad_and_outputIcNS_11char_traitsIcEEEENS_19ostreambuf_iteratorIT_T0_EES6_PKS4_S8_S8_RNS_8ios_baseES4_+0x141>
    22b7: 4d 29 e7                     	subq	%r12, %r15
    22ba: 4d 85 ff                     	testq	%r15, %r15
    22bd: 7e 15                        	jle	0x22d4 <_ZNSt3__116__pad_and_outputIcNS_11char_traitsIcEEEENS_19ostreambuf_iteratorIT_T0_EES6_PKS4_S8_S8_RNS_8ios_baseES4_+0x124>
    22bf: 49 8b 45 00                  	movq	(%r13), %rax
    22c3: 4c 89 ef                     	movq	%r13, %rdi
    22c6: 4c 89 e6                     	movq	%r12, %rsi
    22c9: 4c 89 fa                     	movq	%r15, %rdx
    22cc: ff 50 60                     	callq	*96(%rax)
    22cf: 4c 39 f8                     	cmpq	%r15, %rax
    22d2: 75 1d                        	jne	0x22f1 <_ZNSt3__116__pad_and_outputIcNS_11char_traitsIcEEEENS_19ostreambuf_iteratorIT_T0_EES6_PKS4_S8_S8_RNS_8ios_baseES4_+0x141>
    22d4: 49 c7 46 18 00 00 00 00      	movq	$0, 24(%r14)
    22dc: 64 48 8b 04 25 28 00 00 00   	movq	%fs:40, %rax
    22e5: 48 3b 44 24 30               	cmpq	48(%rsp), %rax
    22ea: 74 18                        	je	0x2304 <_ZNSt3__116__pad_and_outputIcNS_11char_traitsIcEEEENS_19ostreambuf_iteratorIT_T0_EES6_PKS4_S8_S8_RNS_8ios_baseES4_+0x154>
    22ec: e8 1f 01 00 00               	callq	0x2410 <__stack_chk_fail@plt>
    22f1: 45 31 ed                     	xorl	%r13d, %r13d
    22f4: 64 48 8b 04 25 28 00 00 00   	movq	%fs:40, %rax
    22fd: 48 3b 44 24 30               	cmpq	48(%rsp), %rax
    2302: 75 e8                        	jne	0x22ec <_ZNSt3__116__pad_and_outputIcNS_11char_traitsIcEEEENS_19ostreambuf_iteratorIT_T0_EES6_PKS4_S8_S8_RNS_8ios_baseES4_+0x13c>
    2304: 4c 89 e8                     	movq	%r13, %rax
    2307: 48 83 c4 38                  	addq	$56, %rsp
    230b: 5b                           	popq	%rbx
    230c: 41 5c                        	popq	%r12
    230e: 41 5d                        	popq	%r13
    2310: 41 5e                        	popq	%r14
    2312: 41 5f                        	popq	%r15
    2314: 5d                           	popq	%rbp
    2315: c3                           	retq
    2316: 48 89 c3                     	movq	%rax, %rbx
    2319: f6 44 24 18 01               	testb	$1, 24(%rsp)
    231e: 74 0a                        	je	0x232a <_ZNSt3__116__pad_and_outputIcNS_11char_traitsIcEEEENS_19ostreambuf_iteratorIT_T0_EES6_PKS4_S8_S8_RNS_8ios_baseES4_+0x17a>
    2320: 48 8b 7c 24 28               	movq	40(%rsp), %rdi
    2325: e8 86 01 00 00               	callq	0x24b0 <_ZdlPv@plt>
    232a: 48 89 df                     	movq	%rbx, %rdi
    232d: e8 ee 00 00 00               	callq	0x2420 <_Unwind_Resume@plt>
    2332: cc                           	int3
    2333: cc                           	int3
    2334: cc                           	int3
    2335: cc                           	int3
    2336: cc                           	int3
    2337: cc                           	int3
    2338: cc                           	int3
    2339: cc                           	int3
    233a: cc                           	int3
    233b: cc                           	int3
    233c: cc                           	int3
    233d: cc                           	int3
    233e: cc                           	int3
    233f: cc                           	int3

0000000000002340 <__clang_call_terminate>:
    2340: 50                           	pushq	%rax
    2341: e8 1a 01 00 00               	callq	0x2460 <__cxa_begin_catch@plt>
    2346: e8 75 01 00 00               	callq	0x24c0 <_ZSt9terminatev@plt>
    234b: cc                           	int3

Disassembly of section .init:

000000000000234c <_init>:
    234c: f3 0f 1e fa                  	endbr64
    2350: 48 83 ec 08                  	subq	$8, %rsp
    2354: 48 8b 05 7d 13 00 00         	movq	4989(%rip), %rax        # 0x36d8 <memset+0x36d8>
    235b: 48 85 c0                     	testq	%rax, %rax
    235e: 74 02                        	je	0x2362 <_init+0x16>
    2360: ff d0                        	callq	*%rax
    2362: 48 83 c4 08                  	addq	$8, %rsp
    2366: c3                           	retq

Disassembly of section .fini:

0000000000002368 <_fini>:
    2368: f3 0f 1e fa                  	endbr64
    236c: 48 83 ec 08                  	subq	$8, %rsp
    2370: 48 83 c4 08                  	addq	$8, %rsp
    2374: c3                           	retq

Disassembly of section .plt:

0000000000002380 <.plt>:
    2380: ff 35 a2 23 00 00            	pushq	9122(%rip)              # 0x4728 <memset+0x4728>
    2386: ff 25 a4 23 00 00            	jmpq	*9124(%rip)             # 0x4730 <memset+0x4730>
    238c: 0f 1f 40 00                  	nopl	(%rax)

0000000000002390 <__register_frame_info@plt>:
    2390: ff 25 a2 23 00 00            	jmpq	*9122(%rip)             # 0x4738 <memset+0x4738>
    2396: 68 00 00 00 00               	pushq	$0
    239b: e9 e0 ff ff ff               	jmp	0x2380 <.plt>

00000000000023a0 <__cxa_finalize@plt>:
    23a0: ff 25 9a 23 00 00            	jmpq	*9114(%rip)             # 0x4740 <memset+0x4740>
    23a6: 68 01 00 00 00               	pushq	$1
    23ab: e9 d0 ff ff ff               	jmp	0x2380 <.plt>

00000000000023b0 <__deregister_frame_info@plt>:
    23b0: ff 25 92 23 00 00            	jmpq	*9106(%rip)             # 0x4748 <memset+0x4748>
    23b6: 68 02 00 00 00               	pushq	$2
    23bb: e9 c0 ff ff ff               	jmp	0x2380 <.plt>

00000000000023c0 <_ZNKSt3__18ios_base6getlocEv@plt>:
    23c0: ff 25 8a 23 00 00            	jmpq	*9098(%rip)             # 0x4750 <memset+0x4750>
    23c6: 68 03 00 00 00               	pushq	$3
    23cb: e9 b0 ff ff ff               	jmp	0x2380 <.plt>

00000000000023d0 <_ZNKSt3__16locale9use_facetERNS0_2idE@plt>:
    23d0: ff 25 82 23 00 00            	jmpq	*9090(%rip)             # 0x4758 <memset+0x4758>
    23d6: 68 04 00 00 00               	pushq	$4
    23db: e9 a0 ff ff ff               	jmp	0x2380 <.plt>

00000000000023e0 <_ZNSt3__16localeD1Ev@plt>:
    23e0: ff 25 7a 23 00 00            	jmpq	*9082(%rip)             # 0x4760 <memset+0x4760>
    23e6: 68 05 00 00 00               	pushq	$5
    23eb: e9 90 ff ff ff               	jmp	0x2380 <.plt>

00000000000023f0 <_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE3putEc@plt>:
    23f0: ff 25 72 23 00 00            	jmpq	*9074(%rip)             # 0x4768 <memset+0x4768>
    23f6: 68 06 00 00 00               	pushq	$6
    23fb: e9 80 ff ff ff               	jmp	0x2380 <.plt>

0000000000002400 <_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE5flushEv@plt>:
    2400: ff 25 6a 23 00 00            	jmpq	*9066(%rip)             # 0x4770 <memset+0x4770>
    2406: 68 07 00 00 00               	pushq	$7
    240b: e9 70 ff ff ff               	jmp	0x2380 <.plt>

0000000000002410 <__stack_chk_fail@plt>:
    2410: ff 25 62 23 00 00            	jmpq	*9058(%rip)             # 0x4778 <memset+0x4778>
    2416: 68 08 00 00 00               	pushq	$8
    241b: e9 60 ff ff ff               	jmp	0x2380 <.plt>

0000000000002420 <_Unwind_Resume@plt>:
    2420: ff 25 5a 23 00 00            	jmpq	*9050(%rip)             # 0x4780 <memset+0x4780>
    2426: 68 09 00 00 00               	pushq	$9
    242b: e9 50 ff ff ff               	jmp	0x2380 <.plt>

0000000000002430 <_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE6sentryC1ERS3_@plt>:
    2430: ff 25 52 23 00 00            	jmpq	*9042(%rip)             # 0x4788 <memset+0x4788>
    2436: 68 0a 00 00 00               	pushq	$10
    243b: e9 40 ff ff ff               	jmp	0x2380 <.plt>

0000000000002440 <_ZNSt3__18ios_base5clearEj@plt>:
    2440: ff 25 4a 23 00 00            	jmpq	*9034(%rip)             # 0x4790 <memset+0x4790>
    2446: 68 0b 00 00 00               	pushq	$11
    244b: e9 30 ff ff ff               	jmp	0x2380 <.plt>

0000000000002450 <_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE6sentryD1Ev@plt>:
    2450: ff 25 42 23 00 00            	jmpq	*9026(%rip)             # 0x4798 <memset+0x4798>
    2456: 68 0c 00 00 00               	pushq	$12
    245b: e9 20 ff ff ff               	jmp	0x2380 <.plt>

0000000000002460 <__cxa_begin_catch@plt>:
    2460: ff 25 3a 23 00 00            	jmpq	*9018(%rip)             # 0x47a0 <memset+0x47a0>
    2466: 68 0d 00 00 00               	pushq	$13
    246b: e9 10 ff ff ff               	jmp	0x2380 <.plt>

0000000000002470 <_ZNSt3__18ios_base33__set_badbit_and_consider_rethrowEv@plt>:
    2470: ff 25 32 23 00 00            	jmpq	*9010(%rip)             # 0x47a8 <memset+0x47a8>
    2476: 68 0e 00 00 00               	pushq	$14
    247b: e9 00 ff ff ff               	jmp	0x2380 <.plt>

0000000000002480 <__cxa_end_catch@plt>:
    2480: ff 25 2a 23 00 00            	jmpq	*9002(%rip)             # 0x47b0 <memset+0x47b0>
    2486: 68 0f 00 00 00               	pushq	$15
    248b: e9 f0 fe ff ff               	jmp	0x2380 <.plt>

0000000000002490 <_Znwm@plt>:
    2490: ff 25 22 23 00 00            	jmpq	*8994(%rip)             # 0x47b8 <memset+0x47b8>
    2496: 68 10 00 00 00               	pushq	$16
    249b: e9 e0 fe ff ff               	jmp	0x2380 <.plt>

00000000000024a0 <memset@plt>:
    24a0: ff 25 1a 23 00 00            	jmpq	*8986(%rip)             # 0x47c0 <memset+0x47c0>
    24a6: 68 11 00 00 00               	pushq	$17
    24ab: e9 d0 fe ff ff               	jmp	0x2380 <.plt>

00000000000024b0 <_ZdlPv@plt>:
    24b0: ff 25 12 23 00 00            	jmpq	*8978(%rip)             # 0x47c8 <memset+0x47c8>
    24b6: 68 12 00 00 00               	pushq	$18
    24bb: e9 c0 fe ff ff               	jmp	0x2380 <.plt>

00000000000024c0 <_ZSt9terminatev@plt>:
    24c0: ff 25 0a 23 00 00            	jmpq	*8970(%rip)             # 0x47d0 <memset+0x47d0>
    24c6: 68 13 00 00 00               	pushq	$19
    24cb: e9 b0 fe ff ff               	jmp	0x2380 <.plt>

There are some facts to consider.

A context switch could actually occur right in between any two successive assembly instructions, unless the code is wrapped into “critical sections” using appropriate syscalls to instruct an OS explicitly not to.

Thread suspension are resuming are context switches.

Which any shared mutable state (which is what imperative means) there is no guarantee that after resuming (switching of an execution context back to the next assembly instruction) the state has not been partially modified by other thread.

There is in principle no solution to sharing of a mutable state, it is just wrong. This is as fundamental as membranes of biological cells.

A few more facts

You don’t see subtle bugs just because you are ignorant and intentionally not looking.

If your solution relies on Mutexes and Critical Sections, then it is just multiple threads busy-waiting on locks.

Concurrent code and data must be structured differently – in memory, by the runtime and by the language primitives.

Actual abstraction barriers must separate the data and only asynchronous structured message-passing can occur in code.

This requires a proper runtime support for sending and receiving of messages (with structural pattern-matching) and for the “mailboxes” (transactional, append-only storage), etc.

Just a bunch libraries on top of an imperative runtime won’t work. It will only seem to work. The runtime must itself be properly partitioned (structured).

Only Erlang guys did everything right – a principle-based research from the ground up (up to erts).

Shared concurrency for imperative code is a myth. Period.

The solutions

There are mathematically-sound theoretical solutions.

Referential transparency

This is the fundamental property of all binding, both of symbols and within the compound and structured data - once bound everything stays forever - does not change behind your back.

This is the whole point of pure-functional languages like Haskell. All the effort is to preserve and even guarantee this referential transparency property.

These guarantees have various qualitative implications. The most important is the emergent declarative nature of resulting expressions, so they operationally have the same properties as mathematical formulas, expressions of pure logic, finite state machines and can be transformed (without any loss of information) into abstract syntax trees and acyclic graphs in general.

This is the ideal which Haskell community zealously seek to attain.

At most one mutable reference

This is another principal theoretical solution, which is partial referential transparency so to speak. The state has to be encapsulated into a closure, which is traditionally called a ref.

A ref or a reference is just an ADT, and the explicit abstraction barrier keeps the state “invisible” to the pure expressions. They only declare what eventually to do be done with it, whatever it actually might be.

It is remarkable that an Abstract Data Type is the fundamental building block here.

Generalized Abstraction barriers

There are emergent /standard idioms to establish and maintain actual abstraction barriers.

  • type-classes allow to define abstract data types on the basis of behaviors or sets of required interfaces to be implemented (to be an X is to quack like an X and walk like an X).
  • Monad (in the context of programming languages) is “even more generic” type-class for defining Abstract Data Types, which in turn are abstraction barriers, partitions or abstract “membranes”. It is a “standard shape or form” for an ADT, which itself is also an /instance of a particular type-class (a set of required interfaces).

    And also form (an instance of) a Monad (type-class). And this is literally it.

    Keeping state “inside a Monad” (behind an abstraction barrier) is how a type-system-level guarantees of “safety” (yes, of non-broken referential transparency) could be obtained.

    In languages other than Haskell care should be taken of maintaining at most one mutable reference. In Haskell there is no mutation possible in principle (only shadowing and extending).

Async

The most adequate case for using a Monad (which is, again, just an ADT, an instance of a standard type-class) is to separate pure functions form async procedures, which are fundamentally different forms of computation.

(An async procedure requires an implicit distinct execution context and special signalling for returning its result).

A monad (as a “generic” type-class) is the way to define abstraction barrier between pure mathematical functions and asynchronous procedures.

A vertical arrow

The fundamental principle is that values could be passed strictly in only one direction - into an async context, and never “back”, which has a deep relation with the concept of an “arrow”, found at the “core of everything” (a -> b).

The point is that these async procedures could be composed just like ordinary pure functions (using nesting, which is the only way a composition could be defined declaratively), but behind its abstraction barrier, using a distinct composition operator (not just our pure .) or “inside of a Monad” as they prefer to say.

And a horizontal arrow

Think of introducing a vertical arrow for “lifting of values” (which will never “come back” to the pure realm which they have left - notice this finest esoteric prose) and a “lifted” (or specialized for this particular context) ., which is traditionally bound to a >>=, and suggest an arrow, which imply a direction (of a single step of any process).

And, again, this notion of a “vertical arrow”, which crosses an abstraction barrier (it is a Kleisli arrow after all) in only one direction, is “it”.

an ADT for ADTs

A Monad, as you see, is a “lift” (a vertical error) for values and “composition” (specialized dot) for computations in this particular instance or a context.

So one “lift” values (using Kleisli arrows) into a specific context and compose “computations” defined (and evaluated) with means of the same pure language, but behind a type-system ensured and guaranteed to be sound actual abstraction barrier.

This is general-enough (as general, in fact, as untyped Lambda Calculus) because it is, again, just an ADT for ADTs or nesting of ADTs. It corresponds to the fundamental notion of “AND ALSO” (an instance of) quacks like a duck.

Comosition of type-classes

Whole type-classes can be composed (to form a new whole), using instantiation (implementing an interface within an ADT module) instead of some explicit type-level combinators (the type-system will maintain its own context to track who implements what), and this is, for the third time in this essay, “it” again.

Everything boils down to partitions, nesting and arrows - proper abstractions, generalized form Molecular Biology and What Is.

Erlang

Erlang, being dynamically but strongly-typed language, reinforces abstraction barriers at interfaces (where else?). User-facing code is a pure-functional language, augmented with a minimum of carefully crafted concurrency primitives.

One can think of an actor as a tail-recursive function, which passes the state in a parameter (thus ensuring the at most one mutable reference property).

Asynchronous send function (the ! infix operator) always succeeds and could be seen as an identity function on the data argument (think that it could be /partially applied to the “address” first).

The reseive expression is just like case (pattern-matching) expression on an implicit parameter, which is has messages as values.

To be fair, these concurrency primitives are NOT strictly pure-functional, but the referential-transparency property is preserved - same input (/including the same contents of a mailbox) - same output. Always.

The spawn primitive is definitely not a function, so it is a plain hack. However, it is fully-deterministic within the context of the whole Erlang node.

Types are written in an additional DSL and checked by a specialized tools, which is also a proper design.

Behaviors

These building blocks (at the levels of libraries) can be thought off as sets of mutually-recursive generic functions (within a module), being parameterized by “callbacks” which contain user’s code.

This is the very same fundamental abstraction by parameterization principle, applied at the level of interfaces.

The functions (a callback is just a function) send and receive messages according to well-defined protocol.

Any protocol, in turn, is just an informally stated explicit set of rules to be implemented (followed).

At a system (OTP) level there are protocols (with rely on universal message-passing) everywhere. This is how telecommunication hardware (systems) has been build.

Erlang is simply a great language. It is well-researched and well-designed both at the user-facing (syntax, semantics) level and at the level of a properly designed standard library (OTP) and the partitioned /runtime system (written in Erlang itself and some portable C).

It takes time, like with any art form, to understand appreciate the details as well as the principles everything is based upon. Erlang is a marvel of craftsmanship.

Author: <schiptsov@gmail.com>

Email: lngnmn2@yahoo.com

Created: 2023-08-08 Tue 18:37

Emacs 29.1.50 (Org mode 9.7-pre)