1/*	$NetBSD: coffhdrfix.c,v 1.1 2005/12/29 15:20:09 tsutsui Exp $	*/
2
3/*-
4 * Copyright (c) 2004 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by UCHIYAMA Yasushi.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/* fixup GNU binutils file offset error. */
33
34#include <stdio.h>
35#include <sys/types.h>
36#include <sys/fcntl.h>
37#include <sys/mman.h>
38
39typedef uint8_t Coff_Byte;
40typedef uint8_t Coff_Half[2];
41typedef uint8_t Coff_Word[4];
42
43#define	ECOFF_OMAGIC		0407
44#define	ECOFF_MAGIC_MIPSEB	0x0160
45
46struct coff_filehdr {
47	Coff_Half	f_magic;
48	Coff_Half	f_nscns;
49	Coff_Word	f_timdat;
50	Coff_Word	f_symptr;
51	Coff_Word	f_nsyms;
52	Coff_Half	f_opthdr;
53	Coff_Half	f_flags;
54};
55
56struct coff_aouthdr {
57	Coff_Half	a_magic;
58	Coff_Half	a_vstamp;
59	Coff_Word	a_tsize;
60	Coff_Word	a_dsize;
61	Coff_Word	a_bsize;
62	Coff_Word	a_entry;
63	Coff_Word	a_tstart;
64	Coff_Word	a_dstart;
65};
66
67#define	COFF_GET_HALF(w)	((w)[1] | ((w)[0] << 8))
68#define	COFF_SET_HALF(w,v)	((w)[1] = (uint8_t)(v),			\
69				(w)[0] = (uint8_t)((v) >> 8))
70#define	COFF_GET_WORD(w)	((w)[3] | ((w)[2] << 8) | 		\
71				((w)[1] << 16) | ((w)[0] << 24))
72#define	COFF_SET_WORD(w,v)	((w)[3] = (uint8_t)(v),			\
73				(w)[2] = (uint8_t)((v) >> 8),		\
74				(w)[1] = (uint8_t)((v) >> 16),		\
75				(w)[0] = (uint8_t)((v) >> 24))
76
77#define	FILHSZ	sizeof(struct coff_filehdr)
78#define	SCNHSZ	40
79
80int
81main(int argc, char *argp[])
82{
83	int fd, fdout, fileoff, i;
84	struct coff_filehdr file;
85	struct coff_aouthdr aout;
86	char fname[256];
87	char buf[1024];
88
89	if (argc < 3)
90		return 0;
91
92	if ((fd = open(argp[1], O_RDWR)) < 0) {
93		perror(0);
94		return 0;
95	}
96	read(fd, &file, sizeof file);
97	read(fd, &aout, sizeof aout);
98
99	if (COFF_GET_HALF(file.f_magic) != ECOFF_MAGIC_MIPSEB) {
100		fprintf (stderr, "not COFF file.\n");
101		return 0;
102	}
103	if (COFF_GET_HALF(aout.a_magic) != ECOFF_OMAGIC) {
104		fprintf (stderr, "not OMAGIC.\n");
105		return 0;
106	}
107	fprintf(stderr, "File: magic: 0x%04x flags: 0x%04x\n",
108	    COFF_GET_HALF(file.f_magic), COFF_GET_HALF(file.f_flags));
109	fprintf(stderr, "Aout: magic: 0x%04x vstamp: %d\n",
110	    COFF_GET_HALF(aout.a_magic), COFF_GET_HALF(aout.a_vstamp));
111
112	fileoff = (FILHSZ +
113	    COFF_GET_HALF(file.f_opthdr) +
114	    COFF_GET_HALF(file.f_nscns) * SCNHSZ + 7) & ~7;
115	fprintf(stderr, "File offset: 0x%x\n", fileoff);
116	close(fd);
117
118	if ((fdout = open(argp[2], O_CREAT | O_TRUNC | O_RDWR, 0644)) < 0) {
119		perror (0);
120		return 0;
121	}
122	fd = open(argp[1], O_RDWR);
123	read(fd, buf, fileoff);
124	write(fdout, buf, fileoff);
125	lseek(fd, 8, SEEK_CUR);
126	while ((i = read(fd, buf, 1024)) > 0)
127		write(fdout, buf, i);
128	close(fd);
129	close(fdout);
130
131	return 0;
132}
133