// File: ksherlock[P]wdc-utils/link.cpp
// Function: main
int main(int argc, char **argv) {


	int c;
	while ((c = getopt(argc, argv, "vCXSL:l:o:t:")) != -1) {
		switch(c) {
			case 'h': usage(0); break;

			case 'v': flags.v = true; break;
			case 'S': flags.S = true; break;

			case '1': flags.omf_flags |= OMF_V1; break;
			case 'X': flags.omf_flags |= OMF_NO_EXPRESS; break;
			case 'C': flags.omf_flags |= OMF_NO_SUPER; break;

			case 'o': flags.o = optarg; break;

			case 'l': {
				if (*optarg) flags.l.emplace_back(optarg);
				break;
			}
			case 'L': {
				std::string tmp(optarg);
				if (tmp.empty()) tmp = ".";
				if (tmp.back() != '/') tmp.push_back('/');
				flags.L.emplace_back(std::move(tmp));
				break;
			}
			case 't': {
				// -t xx[:xxxx] -- set file/auxtype.
				if (!parse_ft(optarg)) {
					errx(EX_USAGE, "Invalid -t argument: %s", optarg);
				}
				break;
			}


			case ':':
			case '?':
			default:
				usage(EX_USAGE);
				break;
		}
	}

	argc -= optind;
	argv += optind;

	if (argc == 0) usage(EX_USAGE);

	init();

	for (int i = 0 ; i < argc; ++i) {
		if (!one_file(argv[i])) flags.errors++;
	}


	if (flags.v && !undefined_symbols.empty()) {
		printf("Undefined Symbols:\n");
		for (const auto & s : undefined_symbols) {
			printf("%s\n", s.c_str());
		}
		printf("\n");
	}

	if (!undefined_symbols.empty()) libraries();
	//

	if (!undefined_symbols.empty()) {

		fprintf(stderr, "Unable to resolve the following symbols:\n");
		for (auto &s : undefined_symbols) fprintf(stderr, "%s\n", s.c_str());

		exit(EX_DATAERR);
	}

	generate_end();
	simplify();


	if (flags.v) {
		for (const auto &s : sections) {
			//if (s.flags & SEC_REF_ONLY) continue;
			printf("section %3d %-20s $%04x $%04x\n",
				s.number, s.name.c_str(), (uint32_t)s.data.size(), s.size);
		}
		fputs("\n", stdout);
	}

	build_omf_segments();

	if (flags.v) {
		for (const auto &s : omf_segments) {
			printf("segment %3d %-20s $%04x\n",
				s.segnum, s.segname.c_str(), (uint32_t)s.data.size());

			for (auto &r : s.relocs) {
				printf("  %02x %02x %06x %06x\n",
					r.size, r.shift, r.offset, r.value);
			}
			for (auto &r : s.intersegs) {
				printf("  %02x %02x %06x %02x %04x %06x\n",
					r.size, r.shift, r.offset, r.file, r.segment, r.segment_offset);
			}
		}
	}

	if (flags.o.empty()) flags.o = "out.omf";
	if (!flags.file_type) {
		flags.file_type = 0xb3;
	}

	int set_file_type(const std::string &path, uint16_t file_type, uint32_t aux_type);

	save_omf(flags.o, omf_segments, flags.omf_flags);
	set_file_type(flags.o, flags.file_type, flags.aux_type);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1e0, %rsp            # imm = 0x1E0
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl -0x8(%rbp), %edi
movq -0x10(%rbp), %rsi
leaq 0x235d5(%rip), %rdx     # 0x2b86c
callq 0x30b0
movl %eax, -0x14(%rbp)
cmpl $-0x1, %eax
je 0x8536
movl -0x14(%rbp), %eax
addl $-0x31, %eax
movl %eax, %ecx
movq %rcx, -0x168(%rbp)
subl $0x45, %eax
ja 0x8527
movq -0x168(%rbp), %rax
leaq 0x22dde(%rip), %rcx     # 0x2b0ac
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
xorl %edi, %edi
callq 0x8240
jmp 0x8531
movb $0x1, 0x37056(%rip)     # 0x3f340
jmp 0x8531
movb $0x1, 0x3704b(%rip)     # 0x3f341
jmp 0x8531
movl 0x370a3(%rip), %eax     # 0x3f3a4
orl $0x1, %eax
movl %eax, 0x3709a(%rip)     # 0x3f3a4
jmp 0x8531
movl 0x3708f(%rip), %eax     # 0x3f3a4
orl $0x8, %eax
movl %eax, 0x37086(%rip)     # 0x3f3a4
jmp 0x8531
movl 0x3707b(%rip), %eax     # 0x3f3a4
orl $0x2, %eax
movl %eax, 0x37072(%rip)     # 0x3f3a4
jmp 0x8531
movq 0x36c82(%rip), %rax     # 0x3efc0
movq (%rax), %rsi
leaq 0x36ff8(%rip), %rdi     # 0x3f340
addq $0x8, %rdi
callq 0x3440
jmp 0x8531
movq 0x36c63(%rip), %rax     # 0x3efc0
movq (%rax), %rax
cmpb $0x0, (%rax)
je 0x837c
leaq 0x36fd4(%rip), %rdi     # 0x3f340
addq $0x28, %rdi
movq 0x36c49(%rip), %rsi     # 0x3efc0
callq 0xd460
jmp 0x8531
movq 0x36c38(%rip), %rax     # 0x3efc0
movq (%rax), %rax
movq %rax, -0x178(%rbp)
leaq -0x39(%rbp), %rdi
movq %rdi, -0x170(%rbp)
callq 0x3550
movq -0x178(%rbp), %rsi
movq -0x170(%rbp), %rdx
leaq -0x38(%rbp), %rdi
callq 0xbea0
jmp 0x83bb
leaq -0x39(%rbp), %rdi
callq 0x3370
leaq -0x38(%rbp), %rdi
callq 0x3510
testb $0x1, %al
jne 0x83d3
jmp 0x841b
leaq 0x23591(%rip), %rsi     # 0x2b96b
leaq -0x38(%rbp), %rdi
callq 0x3440
jmp 0x83e5
jmp 0x841b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x39(%rbp), %rdi
callq 0x3370
jmp 0x8bf3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x38(%rbp), %rdi
callq 0x31f0
jmp 0x8bf3
leaq -0x38(%rbp), %rdi
callq 0x3270
movsbl (%rax), %eax
cmpl $0x2f, %eax
je 0x843e
leaq -0x38(%rbp), %rdi
movl $0x2f, %esi
callq 0x32d0
jmp 0x843c
jmp 0x843e
leaq 0x36f3b(%rip), %rdi     # 0x3f380
leaq -0x38(%rbp), %rsi
callq 0xd4e0
jmp 0x8450
leaq -0x38(%rbp), %rdi
callq 0x31f0
jmp 0x8531
movq 0x36b5b(%rip), %rax     # 0x3efc0
movq (%rax), %rax
movq %rax, -0x188(%rbp)
leaq -0x71(%rbp), %rdi
movq %rdi, -0x180(%rbp)
callq 0x3550
movq -0x188(%rbp), %rsi
movq -0x180(%rbp), %rdx
leaq -0x70(%rbp), %rdi
callq 0xbea0
jmp 0x8498
leaq -0x70(%rbp), %rdi
callq 0x8010
movb %al, -0x189(%rbp)
jmp 0x84a9
movb -0x189(%rbp), %al
xorb $-0x1, %al
movb %al, -0x18a(%rbp)
leaq -0x70(%rbp), %rdi
callq 0x31f0
leaq -0x71(%rbp), %rdi
callq 0x3370
movb -0x18a(%rbp), %al
testb $0x1, %al
jne 0x84d5
jmp 0x8523
movq 0x36ae4(%rip), %rax     # 0x3efc0
movq (%rax), %rdx
movl $0x40, %edi
leaq 0x2338e(%rip), %rsi     # 0x2b879
movb $0x0, %al
callq 0x35b0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x8515
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x70(%rbp), %rdi
callq 0x31f0
leaq -0x71(%rbp), %rdi
callq 0x3370
jmp 0x8bf3
jmp 0x8531
jmp 0x8527
movl $0x40, %edi
callq 0x8240
jmp 0x8289
movq 0x36a9b(%rip), %rax     # 0x3efd8
movl (%rax), %ecx
movl -0x8(%rbp), %eax
subl %ecx, %eax
movl %eax, -0x8(%rbp)
movq 0x36a8a(%rip), %rax     # 0x3efd8
movl (%rax), %ecx
movq -0x10(%rbp), %rax
movslq %ecx, %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, -0x10(%rbp)
cmpl $0x0, -0x8(%rbp)
jne 0x8572
movl $0x40, %edi
callq 0x8240
callq 0x5660
movl $0x0, -0x78(%rbp)
movl -0x78(%rbp), %eax
cmpl -0x8(%rbp), %eax
jge 0x866a
movq -0x10(%rbp), %rax
movslq -0x78(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x1a0(%rbp)
leaq -0x99(%rbp), %rdi
movq %rdi, -0x198(%rbp)
callq 0x3550
movq -0x1a0(%rbp), %rsi
movq -0x198(%rbp), %rdx
leaq -0x98(%rbp), %rdi
callq 0xbea0
jmp 0x85cc
leaq -0x98(%rbp), %rdi
callq 0x74e0
movb %al, -0x1a1(%rbp)
jmp 0x85e0
movb -0x1a1(%rbp), %al
xorb $-0x1, %al
movb %al, -0x1a2(%rbp)
leaq -0x98(%rbp), %rdi
callq 0x31f0
leaq -0x99(%rbp), %rdi
callq 0x3370
movb -0x1a2(%rbp), %al
testb $0x1, %al
jne 0x8612
jmp 0x865a
movl 0x36d80(%rip), %eax     # 0x3f398
addl $0x1, %eax
movl %eax, 0x36d77(%rip)     # 0x3f398
jmp 0x865a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x8649
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x98(%rbp), %rdi
callq 0x31f0
leaq -0x99(%rbp), %rdi
callq 0x3370
jmp 0x8bf3
jmp 0x865c
movl -0x78(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x78(%rbp)
jmp 0x857e
testb $0x1, 0x36ccf(%rip)     # 0x3f340
je 0x8732
leaq 0x36dca(%rip), %rdi     # 0x3f448
callq 0xd200
testb $0x1, %al
jne 0x8732
leaq 0x231ff(%rip), %rdi     # 0x2b891
movb $0x0, %al
callq 0x3060
leaq 0x36da8(%rip), %rax     # 0x3f448
movq %rax, -0xa8(%rbp)
leaq 0x36d9a(%rip), %rdi     # 0x3f448
callq 0xcc70
movq %rax, -0xb0(%rbp)
leaq 0x36d87(%rip), %rdi     # 0x3f448
callq 0xcca0
movq %rax, -0xb8(%rbp)
leaq -0xb0(%rbp), %rdi
leaq -0xb8(%rbp), %rsi
callq 0xccd0
testb $0x1, %al
jne 0x86e6
jmp 0x8724
leaq -0xb0(%rbp), %rdi
callq 0xcd00
movq %rax, -0xc0(%rbp)
movq -0xc0(%rbp), %rdi
callq 0x3130
movq %rax, %rsi
leaq 0x232a7(%rip), %rdi     # 0x2b9b6
movb $0x0, %al
callq 0x3060
leaq -0xb0(%rbp), %rdi
callq 0xcde0
jmp 0x86cd
leaq 0x232aa(%rip), %rdi     # 0x2b9d5
movb $0x0, %al
callq 0x3060
leaq 0x36d0f(%rip), %rdi     # 0x3f448
callq 0xd200
testb $0x1, %al
jne 0x8747
callq 0x7e30
leaq 0x36cfa(%rip), %rdi     # 0x3f448
callq 0xd200
testb $0x1, %al
jne 0x8820
movq 0x3686e(%rip), %rax     # 0x3efd0
movq (%rax), %rdi
leaq 0x23139(%rip), %rsi     # 0x2b8a5
movb $0x0, %al
callq 0x3470
leaq 0x36cce(%rip), %rax     # 0x3f448
movq %rax, -0xc8(%rbp)
leaq 0x36cc0(%rip), %rdi     # 0x3f448
callq 0xcc70
movq %rax, -0xd0(%rbp)
leaq 0x36cad(%rip), %rdi     # 0x3f448
callq 0xcca0
movq %rax, -0xd8(%rbp)
leaq -0xd0(%rbp), %rdi
leaq -0xd8(%rbp), %rsi
callq 0xccd0
testb $0x1, %al
jne 0x87c0
jmp 0x8816
leaq -0xd0(%rbp), %rdi
callq 0xcd00
movq %rax, -0xe0(%rbp)
movq 0x367f6(%rip), %rax     # 0x3efd0
movq (%rax), %rax
movq %rax, -0x1b0(%rbp)
movq -0xe0(%rbp), %rdi
callq 0x3130
movq -0x1b0(%rbp), %rdi
movq %rax, %rdx
leaq 0x231b5(%rip), %rsi     # 0x2b9b6
movb $0x0, %al
callq 0x3470
leaq -0xd0(%rbp), %rdi
callq 0xcde0
jmp 0x87a7
movl $0x41, %edi
callq 0x33e0
callq 0x5f20
callq 0x3e00
testb $0x1, 0x36b0f(%rip)     # 0x3f340
je 0x8919
leaq 0x36ba2(%rip), %rax     # 0x3f3e0
movq %rax, -0xe8(%rbp)
leaq 0x36b94(%rip), %rdi     # 0x3f3e0
callq 0x9d70
movq %rax, -0xf0(%rbp)
leaq 0x36b81(%rip), %rdi     # 0x3f3e0
callq 0x9da0
movq %rax, -0xf8(%rbp)
leaq -0xf0(%rbp), %rdi
leaq -0xf8(%rbp), %rsi
callq 0x9dd0
testb $0x1, %al
jne 0x8884
jmp 0x8903
leaq -0xf0(%rbp), %rdi
callq 0x9e10
movq %rax, -0x100(%rbp)
movq -0x100(%rbp), %rax
movl 0x2c(%rax), %eax
movl %eax, -0x1bc(%rbp)
movq -0x100(%rbp), %rdi
callq 0x3130
movq %rax, -0x1b8(%rbp)
movq -0x100(%rbp), %rdi
addq $0x30, %rdi
callq 0xa700
movl -0x1bc(%rbp), %esi
movq -0x1b8(%rbp), %rdx
movl %eax, %ecx
movq -0x100(%rbp), %rax
movl 0x28(%rax), %r8d
leaq 0x22fe4(%rip), %rdi     # 0x2b8cf
movb $0x0, %al
callq 0x3060
leaq -0xf0(%rbp), %rdi
callq 0xa070
jmp 0x886b
movq 0x3669e(%rip), %rax     # 0x3efa8
movq (%rax), %rsi
leaq 0x230c1(%rip), %rdi     # 0x2b9d5
callq 0x33b0
callq 0x6590
testb $0x1, 0x36a1b(%rip)     # 0x3f340
je 0x8b6a
leaq 0x36c96(%rip), %rax     # 0x3f5c8
movq %rax, -0x108(%rbp)
leaq 0x36c88(%rip), %rdi     # 0x3f5c8
callq 0xd560
movq %rax, -0x110(%rbp)
leaq 0x36c75(%rip), %rdi     # 0x3f5c8
callq 0xd590
movq %rax, -0x118(%rbp)
leaq -0x110(%rbp), %rdi
leaq -0x118(%rbp), %rsi
callq 0xd5c0
testb $0x1, %al
jne 0x897b
jmp 0x8b68
leaq -0x110(%rbp), %rdi
callq 0xd600
movq %rax, -0x120(%rbp)
movq -0x120(%rbp), %rax
movzwl (%rax), %eax
movl %eax, -0x1cc(%rbp)
movq -0x120(%rbp), %rdi
addq $0x30, %rdi
callq 0x3130
movq %rax, -0x1c8(%rbp)
movq -0x120(%rbp), %rdi
addq $0x50, %rdi
callq 0xa700
movl -0x1cc(%rbp), %esi
movq -0x1c8(%rbp), %rdx
movl %eax, %ecx
leaq 0x22f13(%rip), %rdi     # 0x2b8ee
movb $0x0, %al
callq 0x3060
movq -0x120(%rbp), %rax
addq $0x80, %rax
movq %rax, -0x128(%rbp)
movq -0x128(%rbp), %rdi
callq 0xd620
movq %rax, -0x130(%rbp)
movq -0x128(%rbp), %rdi
callq 0xd650
movq %rax, -0x138(%rbp)
leaq -0x130(%rbp), %rdi
leaq -0x138(%rbp), %rsi
callq 0xd680
testb $0x1, %al
jne 0x8a35
jmp 0x8a8e
leaq -0x130(%rbp), %rdi
callq 0xd6c0
movq %rax, -0x140(%rbp)
movq -0x140(%rbp), %rax
movzbl (%rax), %esi
movq -0x140(%rbp), %rax
movzbl 0x1(%rax), %edx
movq -0x140(%rbp), %rax
movl 0x4(%rax), %ecx
movq -0x140(%rbp), %rax
movl 0x8(%rax), %r8d
leaq 0x22e8e(%rip), %rdi     # 0x2b907
movb $0x0, %al
callq 0x3060
leaq -0x130(%rbp), %rdi
callq 0xd6e0
jmp 0x8a1c
movq -0x120(%rbp), %rax
addq $0x68, %rax
movq %rax, -0x148(%rbp)
movq -0x148(%rbp), %rdi
callq 0xd700
movq %rax, -0x150(%rbp)
movq -0x148(%rbp), %rdi
callq 0xd730
movq %rax, -0x158(%rbp)
leaq -0x150(%rbp), %rdi
leaq -0x158(%rbp), %rsi
callq 0xd760
testb $0x1, %al
jne 0x8adf
jmp 0x8b55
leaq -0x150(%rbp), %rdi
callq 0xd7a0
movq %rax, -0x160(%rbp)
movq -0x160(%rbp), %rax
movzbl (%rax), %esi
movq -0x160(%rbp), %rax
movzbl 0x1(%rax), %edx
movq -0x160(%rbp), %rax
movl 0x4(%rax), %ecx
movq -0x160(%rbp), %rax
movzwl 0x8(%rax), %r8d
movq -0x160(%rbp), %rax
movzwl 0xa(%rax), %r9d
movq -0x160(%rbp), %rax
movl 0xc(%rax), %eax
leaq 0x22de4(%rip), %rdi     # 0x2b91e
movl %eax, (%rsp)
movb $0x0, %al
callq 0x3060
leaq -0x150(%rbp), %rdi
callq 0xd7c0
jmp 0x8ac6
jmp 0x8b57
leaq -0x110(%rbp), %rdi
callq 0xd7e0
jmp 0x895f
jmp 0x8b6a
leaq 0x367cf(%rip), %rdi     # 0x3f340
addq $0x8, %rdi
callq 0x3510
testb $0x1, %al
jne 0x8b80
jmp 0x8b97
leaq 0x367b9(%rip), %rdi     # 0x3f340
addq $0x8, %rdi
leaq 0x22dad(%rip), %rsi     # 0x2b93f
callq 0x3440
cmpw $0x0, 0x367fd(%rip)     # 0x3f39c
jne 0x8baa
movw $0xb3, 0x367f2(%rip)    # 0x3f39c
movl 0x367f4(%rip), %edx     # 0x3f3a4
leaq 0x36789(%rip), %rdi     # 0x3f340
addq $0x8, %rdi
leaq 0x36a06(%rip), %rsi     # 0x3f5c8
callq 0x247b0
movw 0x367ce(%rip), %ax      # 0x3f39c
movl 0x367cc(%rip), %edx     # 0x3f3a0
leaq 0x36765(%rip), %rdi     # 0x3f340
addq $0x8, %rdi
movzwl %ax, %esi
callq 0x28ec0
movl -0x4(%rbp), %eax
addq $0x1e0, %rsp            # imm = 0x1E0
popq %rbp
retq
movq -0x48(%rbp), %rdi
callq 0x3540
nopl (%rax)