1da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski/*
2da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * vdso2c - A vdso image preparation tool
3da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * Copyright (c) 2014 Andy Lutomirski and others
4da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * Licensed under the GPL v2
5da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski *
6da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * vdso2c requires stripped and unstripped input.  It would be trivial
7da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * to fully strip the input in here, but, for reasons described below,
8da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * we need to write a section table.  Doing this is more or less
9da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * equivalent to dropping all non-allocatable sections, but it's
10da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * easier to let objcopy handle that instead of doing it ourselves.
11da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * If we ever need to do something fancier than what objcopy provides,
12da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * it would be straightforward to add here.
13da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski *
14da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * We're keep a section table for a few reasons:
15da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski *
16da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * The Go runtime had a couple of bugs: it would read the section
17da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * table to try to figure out how many dynamic symbols there were (it
18da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * shouldn't have looked at the section table at all) and, if there
19da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * were no SHT_SYNDYM section table entry, it would use an
20da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * uninitialized value for the number of symbols.  An empty DYNSYM
21da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * table would work, but I see no reason not to write a valid one (and
22da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * keep full performance for old Go programs).  This hack is only
23da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * needed on x86_64.
24da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski *
25da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * The bug was introduced on 2012-08-31 by:
26da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * https://code.google.com/p/go/source/detail?r=56ea40aac72b
27da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * and was fixed on 2014-06-13 by:
28da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * https://code.google.com/p/go/source/detail?r=fc1cd5e12595
29da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski *
30da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * Binutils has issues debugging the vDSO: it reads the section table to
31da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * find SHT_NOTE; it won't look at PT_NOTE for the in-memory vDSO, which
32da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * would break build-id if we removed the section table.  Binutils
33da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * also requires that shstrndx != 0.  See:
34da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * https://sourceware.org/bugzilla/show_bug.cgi?id=17064
35da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski *
36da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * elfutils might not look for PT_NOTE if there is a section table at
37da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * all.  I don't know whether this matters for any practical purpose.
38da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski *
39da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * For simplicity, rather than hacking up a partial section table, we
40da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * just write a mostly complete one.  We omit non-dynamic symbols,
41da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * though, since they're rather large.
42da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski *
43da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * Once binutils gets fixed, we might be able to drop this for all but
44da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * the 64-bit vdso, since build-id only works in kernel RPMs, and
45da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * systems that update to new enough kernel RPMs will likely update
46da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * binutils in sync.  build-id has never worked for home-built kernel
47da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * RPMs without manual symlinking, and I suspect that no one ever does
48da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski * that.
49da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski */
50da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski
516f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski#include <inttypes.h>
526f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski#include <stdint.h>
536f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski#include <unistd.h>
546f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski#include <stdarg.h>
556f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski#include <stdlib.h>
566f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski#include <stdio.h>
576f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski#include <string.h>
586f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski#include <fcntl.h>
596f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski#include <err.h>
606f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski
616f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski#include <sys/mman.h>
626f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski#include <sys/types.h>
636f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski
64bdfb9bcc25005d06a9c301830bdeb7ca5a0b6ef7H. Peter Anvin#include <tools/le_byteshift.h>
65bdfb9bcc25005d06a9c301830bdeb7ca5a0b6ef7H. Peter Anvin
666f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski#include <linux/elf.h>
676f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski#include <linux/types.h>
686f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski
69011561837dad082a92c0537db2d134e66419c6adAndy Lutomirskiconst char *outfilename;
70011561837dad082a92c0537db2d134e66419c6adAndy Lutomirski
716f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski/* Symbols that we need in vdso2c. */
7218d0a6fd227177fd243993179c90e454d0638b06Andy Lutomirskienum {
73e6577a7ce99a506b587bcd1d2cd803cb45119557Andy Lutomirski	sym_vvar_start,
7418d0a6fd227177fd243993179c90e454d0638b06Andy Lutomirski	sym_vvar_page,
7518d0a6fd227177fd243993179c90e454d0638b06Andy Lutomirski	sym_hpet_page,
76bfad381c0d1e19cae8461e105d8d4387dd2a14feAndy Lutomirski	sym_VDSO_FAKE_SECTION_TABLE_START,
77bfad381c0d1e19cae8461e105d8d4387dd2a14feAndy Lutomirski	sym_VDSO_FAKE_SECTION_TABLE_END,
7818d0a6fd227177fd243993179c90e454d0638b06Andy Lutomirski};
7918d0a6fd227177fd243993179c90e454d0638b06Andy Lutomirski
8018d0a6fd227177fd243993179c90e454d0638b06Andy Lutomirskiconst int special_pages[] = {
8118d0a6fd227177fd243993179c90e454d0638b06Andy Lutomirski	sym_vvar_page,
8218d0a6fd227177fd243993179c90e454d0638b06Andy Lutomirski	sym_hpet_page,
8318d0a6fd227177fd243993179c90e454d0638b06Andy Lutomirski};
8418d0a6fd227177fd243993179c90e454d0638b06Andy Lutomirski
85bfad381c0d1e19cae8461e105d8d4387dd2a14feAndy Lutomirskistruct vdso_sym {
86bfad381c0d1e19cae8461e105d8d4387dd2a14feAndy Lutomirski	const char *name;
87bfad381c0d1e19cae8461e105d8d4387dd2a14feAndy Lutomirski	bool export;
88bfad381c0d1e19cae8461e105d8d4387dd2a14feAndy Lutomirski};
89bfad381c0d1e19cae8461e105d8d4387dd2a14feAndy Lutomirski
90bfad381c0d1e19cae8461e105d8d4387dd2a14feAndy Lutomirskistruct vdso_sym required_syms[] = {
91e6577a7ce99a506b587bcd1d2cd803cb45119557Andy Lutomirski	[sym_vvar_start] = {"vvar_start", true},
92bfad381c0d1e19cae8461e105d8d4387dd2a14feAndy Lutomirski	[sym_vvar_page] = {"vvar_page", true},
93bfad381c0d1e19cae8461e105d8d4387dd2a14feAndy Lutomirski	[sym_hpet_page] = {"hpet_page", true},
94bfad381c0d1e19cae8461e105d8d4387dd2a14feAndy Lutomirski	[sym_VDSO_FAKE_SECTION_TABLE_START] = {
95bfad381c0d1e19cae8461e105d8d4387dd2a14feAndy Lutomirski		"VDSO_FAKE_SECTION_TABLE_START", false
96bfad381c0d1e19cae8461e105d8d4387dd2a14feAndy Lutomirski	},
97bfad381c0d1e19cae8461e105d8d4387dd2a14feAndy Lutomirski	[sym_VDSO_FAKE_SECTION_TABLE_END] = {
98bfad381c0d1e19cae8461e105d8d4387dd2a14feAndy Lutomirski		"VDSO_FAKE_SECTION_TABLE_END", false
99bfad381c0d1e19cae8461e105d8d4387dd2a14feAndy Lutomirski	},
100bfad381c0d1e19cae8461e105d8d4387dd2a14feAndy Lutomirski	{"VDSO32_NOTE_MASK", true},
101bfad381c0d1e19cae8461e105d8d4387dd2a14feAndy Lutomirski	{"VDSO32_SYSENTER_RETURN", true},
102bfad381c0d1e19cae8461e105d8d4387dd2a14feAndy Lutomirski	{"__kernel_vsyscall", true},
103bfad381c0d1e19cae8461e105d8d4387dd2a14feAndy Lutomirski	{"__kernel_sigreturn", true},
104bfad381c0d1e19cae8461e105d8d4387dd2a14feAndy Lutomirski	{"__kernel_rt_sigreturn", true},
1056f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski};
1066f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski
1076f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski__attribute__((format(printf, 1, 2))) __attribute__((noreturn))
1086f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirskistatic void fail(const char *format, ...)
1096f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski{
1106f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski	va_list ap;
1116f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski	va_start(ap, format);
1126f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski	fprintf(stderr, "Error: ");
1136f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski	vfprintf(stderr, format, ap);
114da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski	if (outfilename)
115da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski		unlink(outfilename);
1166f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski	exit(1);
1176f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski	va_end(ap);
1186f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski}
1196f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski
120add4eed0a2abea3951206f504330ee5daf8c178aAndy Lutomirski/*
121b4b31f6101433e4b8ee73779b69b935af07682f8Andy Lutomirski * Evil macros for little-endian reads and writes
122add4eed0a2abea3951206f504330ee5daf8c178aAndy Lutomirski */
123c191920f737a09a7252088f018f6747f0d2f484dH. Peter Anvin#define GLE(x, bits, ifnot)						\
124add4eed0a2abea3951206f504330ee5daf8c178aAndy Lutomirski	__builtin_choose_expr(						\
125bdfb9bcc25005d06a9c301830bdeb7ca5a0b6ef7H. Peter Anvin		(sizeof(*(x)) == bits/8),				\
126bdfb9bcc25005d06a9c301830bdeb7ca5a0b6ef7H. Peter Anvin		(__typeof__(*(x)))get_unaligned_le##bits(x), ifnot)
127add4eed0a2abea3951206f504330ee5daf8c178aAndy Lutomirski
128bdfb9bcc25005d06a9c301830bdeb7ca5a0b6ef7H. Peter Anvinextern void bad_get_le(void);
129b4b31f6101433e4b8ee73779b69b935af07682f8Andy Lutomirski#define LAST_GLE(x)							\
130bdfb9bcc25005d06a9c301830bdeb7ca5a0b6ef7H. Peter Anvin	__builtin_choose_expr(sizeof(*(x)) == 1, *(x), bad_get_le())
131add4eed0a2abea3951206f504330ee5daf8c178aAndy Lutomirski
132c191920f737a09a7252088f018f6747f0d2f484dH. Peter Anvin#define GET_LE(x)							\
133b4b31f6101433e4b8ee73779b69b935af07682f8Andy Lutomirski	GLE(x, 64, GLE(x, 32, GLE(x, 16, LAST_GLE(x))))
134b4b31f6101433e4b8ee73779b69b935af07682f8Andy Lutomirski
135b4b31f6101433e4b8ee73779b69b935af07682f8Andy Lutomirski#define PLE(x, val, bits, ifnot)					\
136b4b31f6101433e4b8ee73779b69b935af07682f8Andy Lutomirski	__builtin_choose_expr(						\
137b4b31f6101433e4b8ee73779b69b935af07682f8Andy Lutomirski		(sizeof(*(x)) == bits/8),				\
138b4b31f6101433e4b8ee73779b69b935af07682f8Andy Lutomirski		put_unaligned_le##bits((val), (x)), ifnot)
139b4b31f6101433e4b8ee73779b69b935af07682f8Andy Lutomirski
140b4b31f6101433e4b8ee73779b69b935af07682f8Andy Lutomirskiextern void bad_put_le(void);
141b4b31f6101433e4b8ee73779b69b935af07682f8Andy Lutomirski#define LAST_PLE(x, val)						\
142b4b31f6101433e4b8ee73779b69b935af07682f8Andy Lutomirski	__builtin_choose_expr(sizeof(*(x)) == 1, *(x) = (val), bad_put_le())
143b4b31f6101433e4b8ee73779b69b935af07682f8Andy Lutomirski
144b4b31f6101433e4b8ee73779b69b935af07682f8Andy Lutomirski#define PUT_LE(x, val)					\
145b4b31f6101433e4b8ee73779b69b935af07682f8Andy Lutomirski	PLE(x, val, 64, PLE(x, val, 32, PLE(x, val, 16, LAST_PLE(x, val))))
146b4b31f6101433e4b8ee73779b69b935af07682f8Andy Lutomirski
147add4eed0a2abea3951206f504330ee5daf8c178aAndy Lutomirski
1486f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski#define NSYMS (sizeof(required_syms) / sizeof(required_syms[0]))
1496f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski
150e6577a7ce99a506b587bcd1d2cd803cb45119557Andy Lutomirski#define BITSFUNC3(name, bits, suffix) name##bits##suffix
151e6577a7ce99a506b587bcd1d2cd803cb45119557Andy Lutomirski#define BITSFUNC2(name, bits, suffix) BITSFUNC3(name, bits, suffix)
152e6577a7ce99a506b587bcd1d2cd803cb45119557Andy Lutomirski#define BITSFUNC(name) BITSFUNC2(name, ELF_BITS, )
153e6577a7ce99a506b587bcd1d2cd803cb45119557Andy Lutomirski
154e6577a7ce99a506b587bcd1d2cd803cb45119557Andy Lutomirski#define INT_BITS BITSFUNC2(int, ELF_BITS, _t)
155c1979c370273fd9f7326ffa27a63b9ddb0f495f4Andy Lutomirski
156c1979c370273fd9f7326ffa27a63b9ddb0f495f4Andy Lutomirski#define ELF_BITS_XFORM2(bits, x) Elf##bits##_##x
157c1979c370273fd9f7326ffa27a63b9ddb0f495f4Andy Lutomirski#define ELF_BITS_XFORM(bits, x) ELF_BITS_XFORM2(bits, x)
158c1979c370273fd9f7326ffa27a63b9ddb0f495f4Andy Lutomirski#define ELF(x) ELF_BITS_XFORM(ELF_BITS, x)
159c1979c370273fd9f7326ffa27a63b9ddb0f495f4Andy Lutomirski
160c1979c370273fd9f7326ffa27a63b9ddb0f495f4Andy Lutomirski#define ELF_BITS 64
1616f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski#include "vdso2c.h"
162c1979c370273fd9f7326ffa27a63b9ddb0f495f4Andy Lutomirski#undef ELF_BITS
163c1979c370273fd9f7326ffa27a63b9ddb0f495f4Andy Lutomirski
164c1979c370273fd9f7326ffa27a63b9ddb0f495f4Andy Lutomirski#define ELF_BITS 32
1656f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski#include "vdso2c.h"
166c1979c370273fd9f7326ffa27a63b9ddb0f495f4Andy Lutomirski#undef ELF_BITS
1676f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski
168da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirskistatic void go(void *raw_addr, size_t raw_len,
169da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski	       void *stripped_addr, size_t stripped_len,
170da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski	       FILE *outfile, const char *name)
1716f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski{
172da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski	Elf64_Ehdr *hdr = (Elf64_Ehdr *)raw_addr;
1736f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski
1746f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski	if (hdr->e_ident[EI_CLASS] == ELFCLASS64) {
175da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski		go64(raw_addr, raw_len, stripped_addr, stripped_len,
176da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski		     outfile, name);
1776f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski	} else if (hdr->e_ident[EI_CLASS] == ELFCLASS32) {
178da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski		go32(raw_addr, raw_len, stripped_addr, stripped_len,
179da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski		     outfile, name);
1806f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski	} else {
181011561837dad082a92c0537db2d134e66419c6adAndy Lutomirski		fail("unknown ELF class\n");
1826f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski	}
1836f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski}
1846f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski
185da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirskistatic void map_input(const char *name, void **addr, size_t *len, int prot)
186da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski{
187da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski	off_t tmp_len;
188da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski
189da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski	int fd = open(name, O_RDONLY);
190da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski	if (fd == -1)
191da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski		err(1, "%s", name);
192da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski
193da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski	tmp_len = lseek(fd, 0, SEEK_END);
194da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski	if (tmp_len == (off_t)-1)
195da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski		err(1, "lseek");
196da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski	*len = (size_t)tmp_len;
197da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski
198da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski	*addr = mmap(NULL, tmp_len, prot, MAP_PRIVATE, fd, 0);
199da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski	if (*addr == MAP_FAILED)
200da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski		err(1, "mmap");
201da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski
202da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski	close(fd);
203da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski}
204da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski
2056f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirskiint main(int argc, char **argv)
2066f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski{
207da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski	size_t raw_len, stripped_len;
208da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski	void *raw_addr, *stripped_addr;
2096f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski	FILE *outfile;
2106f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski	char *name, *tmp;
2116f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski	int namelen;
2126f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski
213da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski	if (argc != 4) {
214da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski		printf("Usage: vdso2c RAW_INPUT STRIPPED_INPUT OUTPUT\n");
2156f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski		return 1;
2166f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski	}
2176f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski
2186f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski	/*
2196f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski	 * Figure out the struct name.  If we're writing to a .so file,
2206f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski	 * generate raw output insted.
2216f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski	 */
222da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski	name = strdup(argv[3]);
2236f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski	namelen = strlen(name);
2246f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski	if (namelen >= 3 && !strcmp(name + namelen - 3, ".so")) {
2256f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski		name = NULL;
2266f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski	} else {
2276f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski		tmp = strrchr(name, '/');
2286f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski		if (tmp)
2296f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski			name = tmp + 1;
2306f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski		tmp = strchr(name, '.');
2316f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski		if (tmp)
2326f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski			*tmp = '\0';
2336f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski		for (tmp = name; *tmp; tmp++)
2346f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski			if (*tmp == '-')
2356f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski				*tmp = '_';
2366f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski	}
2376f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski
238da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski	map_input(argv[1], &raw_addr, &raw_len, PROT_READ);
239da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski	map_input(argv[2], &stripped_addr, &stripped_len, PROT_READ);
2406f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski
241da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski	outfilename = argv[3];
242011561837dad082a92c0537db2d134e66419c6adAndy Lutomirski	outfile = fopen(outfilename, "w");
2436f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski	if (!outfile)
2446f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski		err(1, "%s", argv[2]);
2456f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski
246da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski	go(raw_addr, raw_len, stripped_addr, stripped_len, outfile, name);
2476f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski
248da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski	munmap(raw_addr, raw_len);
249da861e18ecccb5c126b9eb95ff720ce082a46286Andy Lutomirski	munmap(stripped_addr, stripped_len);
2506f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski	fclose(outfile);
2516f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski
252011561837dad082a92c0537db2d134e66419c6adAndy Lutomirski	return 0;
2536f121e548f83674ab4920a4e60afb58d4f61b829Andy Lutomirski}
254