The Go Programming Language

Text file src/libmach/access.c

     1	// Inferno libmach/access.c
     2	// http://code.google.com/p/inferno-os/source/browse/utils/libmach/access.c
     3	//
     4	// 	Copyright © 1994-1999 Lucent Technologies Inc.
     5	// 	Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
     6	// 	Portions Copyright © 1997-1999 Vita Nuova Limited.
     7	// 	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
     8	// 	Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
     9	//	Portions Copyright © 2009 The Go Authors.  All rights reserved.
    10	//
    11	// Permission is hereby granted, free of charge, to any person obtaining a copy
    12	// of this software and associated documentation files (the "Software"), to deal
    13	// in the Software without restriction, including without limitation the rights
    14	// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    15	// copies of the Software, and to permit persons to whom the Software is
    16	// furnished to do so, subject to the following conditions:
    17	//
    18	// The above copyright notice and this permission notice shall be included in
    19	// all copies or substantial portions of the Software.
    20	//
    21	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    22	// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    23	// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    24	// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    25	// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    26	// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    27	// THE SOFTWARE.
    28	
    29	/*
    30	 * functions to read and write an executable or file image
    31	 */
    32	
    33	#include <u.h>
    34	#include <libc.h>
    35	#include <bio.h>
    36	#include <mach.h>
    37	
    38	static	int	mget(Map*, uvlong, void*, int);
    39	static	int	mput(Map*, uvlong, void*, int);
    40	static	Seg*	reloc(Map*, uvlong, vlong*);
    41	
    42	/*
    43	 * routines to get/put various types
    44	 */
    45	int
    46	geta(Map *map, uvlong addr, uvlong *x)
    47	{
    48		uint32 l;
    49		uvlong vl;
    50	
    51		if (mach->szaddr == 8){
    52			if (get8(map, addr, &vl) < 0)
    53				return -1;
    54			*x = vl;
    55			return 1;
    56		}
    57	
    58		if (get4(map, addr, &l) < 0)
    59			return -1;
    60		*x = l;
    61	
    62		return 1;
    63	}
    64	
    65	int
    66	get8(Map *map, uvlong addr, uvlong *x)
    67	{
    68		if (!map) {
    69			werrstr("get8: invalid map");
    70			return -1;
    71		}
    72	
    73		if (map->nsegs == 1 && map->seg[0].fd < 0) {
    74			*x = addr;
    75			return 1;
    76		}
    77		if (mget(map, addr, x, 8) < 0)
    78			return -1;
    79		*x = machdata->swav(*x);
    80		return 1;
    81	}
    82	
    83	int
    84	get4(Map *map, uvlong addr, uint32 *x)
    85	{
    86		if (!map) {
    87			werrstr("get4: invalid map");
    88			return -1;
    89		}
    90	
    91		if (map->nsegs == 1 && map->seg[0].fd < 0) {
    92			*x = addr;
    93			return 1;
    94		}
    95		if (mget(map, addr, x, 4) < 0)
    96			return -1;
    97		*x = machdata->swal(*x);
    98		return 1;
    99	}
   100	
   101	int
   102	get2(Map *map, uvlong addr, ushort *x)
   103	{
   104		if (!map) {
   105			werrstr("get2: invalid map");
   106			return -1;
   107		}
   108	
   109		if (map->nsegs == 1 && map->seg[0].fd < 0) {
   110			*x = addr;
   111			return 1;
   112		}
   113		if (mget(map, addr, x, 2) < 0)
   114			return -1;
   115		*x = machdata->swab(*x);
   116		return 1;
   117	}
   118	
   119	int
   120	get1(Map *map, uvlong addr, uchar *x, int size)
   121	{
   122		uchar *cp;
   123	
   124		if (!map) {
   125			werrstr("get1: invalid map");
   126			return -1;
   127		}
   128	
   129		if (map->nsegs == 1 && map->seg[0].fd < 0) {
   130			cp = (uchar*)&addr;
   131			while (cp < (uchar*)(&addr+1) && size-- > 0)
   132				*x++ = *cp++;
   133			while (size-- > 0)
   134				*x++ = 0;
   135		} else
   136			return mget(map, addr, x, size);
   137		return 1;
   138	}
   139	
   140	int
   141	puta(Map *map, uvlong addr, uvlong v)
   142	{
   143		if (mach->szaddr == 8)
   144			return put8(map, addr, v);
   145	
   146		return put4(map, addr, v);
   147	}
   148	
   149	int
   150	put8(Map *map, uvlong addr, uvlong v)
   151	{
   152		if (!map) {
   153			werrstr("put8: invalid map");
   154			return -1;
   155		}
   156		v = machdata->swav(v);
   157		return mput(map, addr, &v, 8);
   158	}
   159	
   160	int
   161	put4(Map *map, uvlong addr, uint32 v)
   162	{
   163		if (!map) {
   164			werrstr("put4: invalid map");
   165			return -1;
   166		}
   167		v = machdata->swal(v);
   168		return mput(map, addr, &v, 4);
   169	}
   170	
   171	int
   172	put2(Map *map, uvlong addr, ushort v)
   173	{
   174		if (!map) {
   175			werrstr("put2: invalid map");
   176			return -1;
   177		}
   178		v = machdata->swab(v);
   179		return mput(map, addr, &v, 2);
   180	}
   181	
   182	int
   183	put1(Map *map, uvlong addr, uchar *v, int size)
   184	{
   185		if (!map) {
   186			werrstr("put1: invalid map");
   187			return -1;
   188		}
   189		return mput(map, addr, v, size);
   190	}
   191	
   192	static int
   193	mget(Map *map, uvlong addr, void *buf, int size)
   194	{
   195		uvlong off;
   196		Seg *s;
   197	
   198		s = reloc(map, addr, (vlong*)&off);
   199		if (!s)
   200			return -1;
   201		if (s->rw == nil) {
   202			werrstr("unreadable map");
   203			return -1;
   204		}
   205		return s->rw(map, s, off, buf, size, 1);
   206	}
   207	
   208	static int
   209	mput(Map *map, uvlong addr, void *buf, int size)
   210	{
   211		vlong off;
   212		Seg *s;
   213	
   214		s = reloc(map, addr, &off);
   215		if (!s)
   216			return -1;
   217		if (s->rw == nil) {
   218			werrstr("unwritable map");
   219			return -1;
   220		}
   221		return s->rw(map, s, off, buf, size, 0);
   222	}
   223	
   224	/*
   225	 *	convert address to file offset; returns nonzero if ok
   226	 */
   227	static Seg*
   228	reloc(Map *map, uvlong addr, vlong *offp)
   229	{
   230		int i;
   231	
   232		for (i = 0; i < map->nsegs; i++) {
   233			if (map->seg[i].inuse)
   234			if (map->seg[i].b <= addr && addr < map->seg[i].e) {
   235				*offp = addr + map->seg[i].f - map->seg[i].b;
   236				return &map->seg[i];
   237			}
   238		}
   239		werrstr("can't translate address %llux", addr);
   240		return 0;
   241	}

release.r60.3. Except as noted, this content is licensed under a Creative Commons Attribution 3.0 License.