Flushage
[mono.git] / mono / metadata / loader.c
1 /*
2  * loader.c: Image Loader 
3  *
4  * Author:
5  *   Miguel de Icaza (miguel@ximian.com)
6  *
7  * (C) 2001 Ximian, Inc.
8  *
9  * This file is used by the interpreter and the JIT engine to locate
10  * assemblies.  Used to load AssemblyRef and later to resolve various
11  * kinds of `Refs'.
12  *
13  * TODO:
14  *   This should keep track of the assembly versions that we are loading.
15  *
16  */
17 #include <config.h>
18 #include <glib.h>
19 #include <stdio.h>
20 #include <mono/metadata/metadata.h>
21 #include <mono/metadata/image.h>
22 #include <mono/metadata/cil-coff.h>
23 #include "cli.h"
24
25 typedef struct {
26         MonoImage    *img;
27         const char   *name;
28         guint16       ver [4];
29 } ImageInfo;
30
31 static GHashTable *image_hash;
32
33 #define CSIZE(x) (sizeof (x) / 4)
34
35 static void
36 register_image (MonoImage *img)
37 {
38         cli_image_info_t *iinfo = img->image_info;
39         metadata_t *t = &iinfo->cli_metadata;
40         ImageInfo *ii = g_new (ImageInfo, 1);
41         metadata_tableinfo_t *assembly_table = &t->tables [META_TABLE_ASSEMBLY];
42         guint32 cols [9];
43
44         if (assembly_table->base == NULL) {
45                 ii->name = img->name;
46                 ii->ver [0] = 0;
47                 ii->ver [1] = 0;
48                 ii->ver [2] = 0;
49                 ii->ver [3] = 0;
50         } else {
51                 mono_metadata_decode_row (assembly_table, 0, cols, CSIZE (cols));
52                 ii->name = mono_metadata_string_heap (t, cols [7]);
53                 ii->ver [0] = cols [1];
54                 ii->ver [1] = cols [2];
55                 ii->ver [2] = cols [3];
56                 ii->ver [3] = cols [4];
57         }
58
59         if (image_hash == NULL)
60                 image_hash = g_hash_table_new (g_str_hash, g_str_equal);
61
62         g_hash_table_insert (image_hash, (void *) ii->name, ii);
63 }
64
65 static void
66 unregister_image (MonoImage *img)
67 {
68 }
69
70 /**
71  * mono_load_image:
72  * @fname: file that contains the image
73  * @status: pointer to the status that can be returned.
74  *
75  * Returns: on success a pointer to a MonoImage.
76  *
77  * Side Effects: This uses mono_image_open to load the image
78  * and later registers this image.  The image can later be located
79  * with mono_locate_image.
80  */
81 MonoImage *
82 mono_load_image (const char *fname, enum MonoImageOpenStatus *status)
83 {
84         MonoImage *img;
85         
86         img = mono_image_open (fname, status);
87         if (img == NULL)
88                 return NULL;
89
90         register_image (img);
91
92         return img;
93 }
94
95 /**
96  * mono_locate_image:
97  * @name: assembly name to locate.
98  */
99 MonoImage *
100 mono_locate_image (const char *name)
101 {
102         ImageInfo *ii = g_hash_table_lookup (image_hash, name);
103
104         if (ii == NULL)
105                 return NULL;
106         
107         return ii->img;
108 }
109
110 MonoMethod *
111 mono_get_method (cli_image_info_t *iinfo, guint32 token)
112 {
113         MonoMethod *result = g_new0 (MonoMethod, 1);
114         int table = mono_metadata_token_table (token);
115         int index = mono_metadata_token_index (token);
116         metadata_tableinfo_t *tables = iinfo->cli_metadata.tables;
117         const char *loc;
118         const char *sig = NULL;
119         int size;
120         guint32 cols[6];
121
122         /*
123          * We need a context with cli_image_info_t for this module and the assemblies
124          * loaded later to support method refs...
125          */
126         if (table != META_TABLE_METHOD) {
127                 g_assert (table == META_TABLE_MEMBERREF);
128                 mono_metadata_decode_row (&tables [table], index, cols, 3);
129                 g_assert ((cols [0] & 0x07) != 3);
130                 table = META_TABLE_METHOD;
131                 index = cols [0] >> 3;
132                 sig = mono_metadata_blob_heap (&iinfo->cli_metadata, cols [2]);
133                 result->name_idx = cols [1];
134         }
135         
136         mono_metadata_decode_row (&tables [table], index - 1, cols, 6);
137         result->name_idx = cols [3];
138         /* if this is a methodref from another module/assembly, this fails */
139         loc = cli_rva_map (iinfo, cols [0]);
140         g_assert (loc);
141         result->header = mono_metadata_parse_mh (&iinfo->cli_metadata, loc);
142         if (!sig) /* already taken from the methodref */
143                 sig = mono_metadata_blob_heap (&iinfo->cli_metadata, cols [4]);
144         sig = mono_metadata_decode_blob_size (sig, &size);
145         result->signature = mono_metadata_parse_method_signature (&iinfo->cli_metadata, 0, sig, NULL);
146
147         return result;
148 }
149
150 void
151 mono_free_method  (MonoMethod *method)
152 {
153         mono_metadata_free_method_signature (method->signature);
154         mono_metadata_free_mh (method->header);
155         g_free (method);
156 }