Deleted Added
full compact
imgact_aout.c (32286) imgact_aout.c (32446)
1/*
2 * Copyright (c) 1993, David Greenman
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
1/*
2 * Copyright (c) 1993, David Greenman
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $Id: imgact_aout.c,v 1.36 1997/09/02 20:05:33 bde Exp $
26 * $Id: imgact_aout.c,v 1.37 1998/01/06 05:15:25 dyson Exp $
27 */
28
29#include <sys/param.h>
30#include <sys/resourcevar.h>
31#include <sys/exec.h>
32#include <sys/mman.h>
33#include <sys/imgact.h>
34#include <sys/imgact_aout.h>
35#include <sys/kernel.h>
36#include <sys/proc.h>
37#include <sys/sysent.h>
38#include <sys/vnode.h>
27 */
28
29#include <sys/param.h>
30#include <sys/resourcevar.h>
31#include <sys/exec.h>
32#include <sys/mman.h>
33#include <sys/imgact.h>
34#include <sys/imgact_aout.h>
35#include <sys/kernel.h>
36#include <sys/proc.h>
37#include <sys/sysent.h>
38#include <sys/vnode.h>
39#include <sys/systm.h>
39
40#include <vm/vm.h>
41#include <vm/vm_param.h>
42#include <vm/vm_prot.h>
43#include <sys/lock.h>
44#include <vm/pmap.h>
45#include <vm/vm_map.h>
40
41#include <vm/vm.h>
42#include <vm/vm_param.h>
43#include <vm/vm_prot.h>
44#include <sys/lock.h>
45#include <vm/pmap.h>
46#include <vm/vm_map.h>
47#include <vm/vm_object.h>
46#include <vm/vm_extern.h>
47
48static int exec_aout_imgact __P((struct image_params *imgp));
49
50int
51exec_aout_imgact(imgp)
52 struct image_params *imgp;
53{
54 const struct exec *a_out = (const struct exec *) imgp->image_header;
55 struct vmspace *vmspace;
48#include <vm/vm_extern.h>
49
50static int exec_aout_imgact __P((struct image_params *imgp));
51
52int
53exec_aout_imgact(imgp)
54 struct image_params *imgp;
55{
56 const struct exec *a_out = (const struct exec *) imgp->image_header;
57 struct vmspace *vmspace;
56 vm_offset_t vmaddr;
58 struct vnode *vp;
59 vm_object_t object;
60 vm_offset_t text_end, data_end;
57 unsigned long virtual_offset;
58 unsigned long file_offset;
59 unsigned long bss_size;
60 int error;
61
62 /*
63 * Linux and *BSD binaries look very much alike,
64 * only the machine id is different:
65 * 0x64 for Linux, 0x86 for *BSD, 0x00 for BSDI.
66 * NetBSD is in network byte order.. ugh.
67 */
68 if (((a_out->a_magic >> 16) & 0xff) != 0x86 &&
69 ((a_out->a_magic >> 16) & 0xff) != 0 &&
70 ((((int)ntohl(a_out->a_magic)) >> 16) & 0xff) != 0x86)
71 return -1;
72
73 /*
74 * Set file/virtual offset based on a.out variant.
75 * We do two cases: host byte order and network byte order
76 * (for NetBSD compatibility)
77 */
78 switch ((int)(a_out->a_magic & 0xffff)) {
79 case ZMAGIC:
80 virtual_offset = 0;
81 if (a_out->a_text) {
82 file_offset = PAGE_SIZE;
83 } else {
84 /* Bill's "screwball mode" */
85 file_offset = 0;
86 }
87 break;
88 case QMAGIC:
89 virtual_offset = PAGE_SIZE;
90 file_offset = 0;
91 break;
92 default:
93 /* NetBSD compatibility */
94 switch ((int)(ntohl(a_out->a_magic) & 0xffff)) {
95 case ZMAGIC:
96 case QMAGIC:
97 virtual_offset = PAGE_SIZE;
98 file_offset = 0;
99 break;
100 default:
101 return (-1);
102 }
103 }
104
105 bss_size = roundup(a_out->a_bss, PAGE_SIZE);
106
107 /*
108 * Check various fields in header for validity/bounds.
109 */
110 if (/* entry point must lay with text region */
111 a_out->a_entry < virtual_offset ||
112 a_out->a_entry >= virtual_offset + a_out->a_text ||
113
114 /* text and data size must each be page rounded */
115 a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK)
116 return (-1);
117
118 /* text + data can't exceed file size */
119 if (a_out->a_data + a_out->a_text > imgp->attr->va_size)
120 return (EFAULT);
121
122 /*
123 * text/data/bss must not exceed limits
124 */
125 if (/* text can't exceed maximum text size */
126 a_out->a_text > MAXTSIZ ||
127
128 /* data + bss can't exceed rlimit */
129 a_out->a_data + bss_size >
130 imgp->proc->p_rlimit[RLIMIT_DATA].rlim_cur)
131 return (ENOMEM);
132
133 /* copy in arguments and/or environment from old process */
134 error = exec_extract_strings(imgp);
135 if (error)
136 return (error);
137
138 /*
139 * Destroy old process VM and create a new one (with a new stack)
140 */
141 exec_new_vmspace(imgp);
142
143 /*
144 * The vm space can be changed by exec_new_vmspace
145 */
146 vmspace = imgp->proc->p_vmspace;
147
61 unsigned long virtual_offset;
62 unsigned long file_offset;
63 unsigned long bss_size;
64 int error;
65
66 /*
67 * Linux and *BSD binaries look very much alike,
68 * only the machine id is different:
69 * 0x64 for Linux, 0x86 for *BSD, 0x00 for BSDI.
70 * NetBSD is in network byte order.. ugh.
71 */
72 if (((a_out->a_magic >> 16) & 0xff) != 0x86 &&
73 ((a_out->a_magic >> 16) & 0xff) != 0 &&
74 ((((int)ntohl(a_out->a_magic)) >> 16) & 0xff) != 0x86)
75 return -1;
76
77 /*
78 * Set file/virtual offset based on a.out variant.
79 * We do two cases: host byte order and network byte order
80 * (for NetBSD compatibility)
81 */
82 switch ((int)(a_out->a_magic & 0xffff)) {
83 case ZMAGIC:
84 virtual_offset = 0;
85 if (a_out->a_text) {
86 file_offset = PAGE_SIZE;
87 } else {
88 /* Bill's "screwball mode" */
89 file_offset = 0;
90 }
91 break;
92 case QMAGIC:
93 virtual_offset = PAGE_SIZE;
94 file_offset = 0;
95 break;
96 default:
97 /* NetBSD compatibility */
98 switch ((int)(ntohl(a_out->a_magic) & 0xffff)) {
99 case ZMAGIC:
100 case QMAGIC:
101 virtual_offset = PAGE_SIZE;
102 file_offset = 0;
103 break;
104 default:
105 return (-1);
106 }
107 }
108
109 bss_size = roundup(a_out->a_bss, PAGE_SIZE);
110
111 /*
112 * Check various fields in header for validity/bounds.
113 */
114 if (/* entry point must lay with text region */
115 a_out->a_entry < virtual_offset ||
116 a_out->a_entry >= virtual_offset + a_out->a_text ||
117
118 /* text and data size must each be page rounded */
119 a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK)
120 return (-1);
121
122 /* text + data can't exceed file size */
123 if (a_out->a_data + a_out->a_text > imgp->attr->va_size)
124 return (EFAULT);
125
126 /*
127 * text/data/bss must not exceed limits
128 */
129 if (/* text can't exceed maximum text size */
130 a_out->a_text > MAXTSIZ ||
131
132 /* data + bss can't exceed rlimit */
133 a_out->a_data + bss_size >
134 imgp->proc->p_rlimit[RLIMIT_DATA].rlim_cur)
135 return (ENOMEM);
136
137 /* copy in arguments and/or environment from old process */
138 error = exec_extract_strings(imgp);
139 if (error)
140 return (error);
141
142 /*
143 * Destroy old process VM and create a new one (with a new stack)
144 */
145 exec_new_vmspace(imgp);
146
147 /*
148 * The vm space can be changed by exec_new_vmspace
149 */
150 vmspace = imgp->proc->p_vmspace;
151
148 /*
149 * Map text/data read/execute
150 */
151 vmaddr = virtual_offset;
152 error =
153 vm_mmap(&vmspace->vm_map, /* map */
154 &vmaddr, /* address */
155 a_out->a_text + a_out->a_data, /* size */
156 VM_PROT_READ | VM_PROT_EXECUTE, /* protection */
157 VM_PROT_ALL, /* max protection */
158 MAP_PRIVATE | MAP_FIXED, /* flags */
159 (caddr_t)imgp->vp, /* vnode */
160 file_offset); /* offset */
152 vp = imgp->vp;
153 object = vp->v_object;
154 vm_object_reference(object);
155
156 text_end = virtual_offset + a_out->a_text;
157 error = vm_map_insert(&vmspace->vm_map, object,
158 file_offset,
159 virtual_offset, text_end,
160 VM_PROT_READ | VM_PROT_EXECUTE, VM_PROT_ALL,
161 MAP_COPY_NEEDED | MAP_COPY_ON_WRITE);
161 if (error)
162 return (error);
163
162 if (error)
163 return (error);
164
164 /*
165 * allow writing of data
166 */
167 vm_map_protect(&vmspace->vm_map,
168 vmaddr + a_out->a_text,
169 vmaddr + a_out->a_text + a_out->a_data,
170 VM_PROT_ALL,
171 FALSE);
172
173 if (bss_size != 0) {
174 /*
175 * Allocate demand-zeroed area for uninitialized data
176 * "bss" = 'block started by symbol' - named after the IBM 7090
177 * instruction of the same name.
178 */
179 vmaddr = virtual_offset + a_out->a_text + a_out->a_data;
180 error = vm_map_find(&vmspace->vm_map, NULL, 0,
181 &vmaddr, bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0);
165 data_end = text_end + a_out->a_data;
166 if (a_out->a_data) {
167 vm_object_reference(object);
168 error = vm_map_insert(&vmspace->vm_map, object,
169 file_offset + a_out->a_text,
170 text_end, data_end,
171 VM_PROT_ALL, VM_PROT_ALL,
172 MAP_COPY_NEEDED | MAP_COPY_ON_WRITE);
182 if (error)
183 return (error);
184 }
185
173 if (error)
174 return (error);
175 }
176
177 pmap_object_init_pt(&vmspace->vm_pmap, virtual_offset,
178 object, (vm_pindex_t) OFF_TO_IDX(file_offset),
179 a_out->a_text + a_out->a_data, 0);
180
181 if (bss_size) {
182 error = vm_map_insert(&vmspace->vm_map, NULL, 0,
183 data_end, data_end + bss_size,
184 VM_PROT_ALL, VM_PROT_ALL, 0);
185 if (error)
186 return (error);
187 }
188
186 /* Fill in process VM information */
187 vmspace->vm_tsize = a_out->a_text >> PAGE_SHIFT;
188 vmspace->vm_dsize = (a_out->a_data + bss_size) >> PAGE_SHIFT;
189 vmspace->vm_taddr = (caddr_t) virtual_offset;
190 vmspace->vm_daddr = (caddr_t) virtual_offset + a_out->a_text;
191
192 /* Fill in image_params */
193 imgp->interpreted = 0;
194 imgp->entry_addr = a_out->a_entry;
195
196 imgp->proc->p_sysent = &aout_sysvec;
197
198 /* Indicate that this file should not be modified */
199 imgp->vp->v_flag |= VTEXT;
200
201 return (0);
202}
203
204/*
205 * Tell kern_execve.c about it, with a little help from the linker.
206 * Since `const' objects end up in the text segment, TEXT_SET is the
207 * correct directive to use.
208 */
209static const struct execsw aout_execsw = { exec_aout_imgact, "a.out" };
210TEXT_SET(execsw_set, aout_execsw);
189 /* Fill in process VM information */
190 vmspace->vm_tsize = a_out->a_text >> PAGE_SHIFT;
191 vmspace->vm_dsize = (a_out->a_data + bss_size) >> PAGE_SHIFT;
192 vmspace->vm_taddr = (caddr_t) virtual_offset;
193 vmspace->vm_daddr = (caddr_t) virtual_offset + a_out->a_text;
194
195 /* Fill in image_params */
196 imgp->interpreted = 0;
197 imgp->entry_addr = a_out->a_entry;
198
199 imgp->proc->p_sysent = &aout_sysvec;
200
201 /* Indicate that this file should not be modified */
202 imgp->vp->v_flag |= VTEXT;
203
204 return (0);
205}
206
207/*
208 * Tell kern_execve.c about it, with a little help from the linker.
209 * Since `const' objects end up in the text segment, TEXT_SET is the
210 * correct directive to use.
211 */
212static const struct execsw aout_execsw = { exec_aout_imgact, "a.out" };
213TEXT_SET(execsw_set, aout_execsw);