Line data Source code
1 : /* Copyright (C) 2010-2026 Free Software Foundation, Inc.
2 :
3 : This file is part of GCC.
4 :
5 : GCC is free software; you can redistribute it and/or modify it under
6 : the terms of the GNU General Public License as published by the Free
7 : Software Foundation; either version 3, or (at your option) any later
8 : version.
9 :
10 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : for more details.
14 :
15 : You should have received a copy of the GNU General Public License
16 : along with GCC; see the file COPYING3. If not see
17 : <http://www.gnu.org/licenses/>. */
18 :
19 : #include "rust-system.h"
20 : #include "coretypes.h"
21 : #include "target.h"
22 : #include "tree.h"
23 : #include "memmodel.h"
24 : #include "tm_p.h"
25 : #include "diagnostic.h"
26 : #include "simple-object.h"
27 : #include "stor-layout.h"
28 : #include "intl.h"
29 : #include "output.h" /* for assemble_string */
30 : #include "common/common-target.h"
31 :
32 : // satisfy intellisense
33 : #include "options.h"
34 :
35 : /* The segment name we pass to simple_object_start_read to find Rust
36 : export data. */
37 :
38 : #ifndef RUST_EXPORT_SEGMENT_NAME
39 : #define RUST_EXPORT_SEGMENT_NAME "__GNU_RUST"
40 : #endif
41 :
42 : /* The section name we use when reading and writing export data. */
43 :
44 : #ifndef RUST_EXPORT_SECTION_NAME
45 : #define RUST_EXPORT_SECTION_NAME ".rust_export"
46 : #endif
47 :
48 : #ifndef TARGET_AIX_OS
49 : #define TARGET_AIX_OS 0
50 : #endif
51 :
52 : /* Return whether or not GCC has reported any errors. */
53 :
54 : bool
55 80707 : saw_errors (void)
56 : {
57 80707 : return errorcount != 0 || sorrycount != 0;
58 : }
59 :
60 : /* Return the alignment in bytes of a struct field of type T. */
61 :
62 : unsigned int
63 0 : rust_field_alignment (tree t)
64 : {
65 0 : unsigned int v;
66 :
67 0 : v = TYPE_ALIGN (t);
68 :
69 : #ifdef BIGGEST_FIELD_ALIGNMENT
70 : if (v > BIGGEST_FIELD_ALIGNMENT)
71 : v = BIGGEST_FIELD_ALIGNMENT;
72 : #endif
73 :
74 : #ifdef ADJUST_FIELD_ALIGN
75 0 : v = ADJUST_FIELD_ALIGN (NULL_TREE, t, v);
76 : #endif
77 :
78 0 : return v / BITS_PER_UNIT;
79 : }
80 :
81 : /* This is called by the Rust frontend proper to add data to the
82 : section containing Rust export data. */
83 :
84 : void
85 0 : rust_write_export_data (const char *bytes, unsigned int size)
86 : {
87 0 : static section *sec;
88 :
89 0 : if (sec == NULL)
90 : {
91 0 : gcc_assert (targetm_common.have_named_sections);
92 0 : sec = get_section (RUST_EXPORT_SECTION_NAME,
93 : TARGET_AIX_OS ? SECTION_EXCLUDE : SECTION_DEBUG, NULL);
94 : }
95 :
96 0 : switch_to_section (sec);
97 0 : assemble_string (bytes, size);
98 0 : }
99 :
100 : /* The rust_read_export_data function is called by the Rust frontend
101 : proper to read Rust export data from an object file. FD is a file
102 : descriptor open for reading. OFFSET is the offset within the file
103 : where the object file starts; this will be 0 except when reading an
104 : archive. On success this returns NULL and sets *PBUF to a buffer
105 : allocated using malloc, of size *PLEN, holding the export data. If
106 : the data is not found, this returns NULL and sets *PBUF to NULL and
107 : *PLEN to 0. If some error occurs, this returns an error message
108 : and sets *PERR to an errno value or 0 if there is no relevant
109 : errno. */
110 :
111 : const char *
112 24 : rust_read_export_data (int fd, off_t offset, char **pbuf, size_t *plen,
113 : int *perr)
114 : {
115 24 : simple_object_read *sobj;
116 24 : const char *errmsg;
117 24 : off_t sec_offset;
118 24 : off_t sec_length;
119 24 : int found;
120 24 : char *buf;
121 24 : ssize_t c;
122 :
123 24 : *pbuf = NULL;
124 24 : *plen = 0;
125 :
126 24 : sobj = simple_object_start_read (fd, offset, RUST_EXPORT_SEGMENT_NAME,
127 : &errmsg, perr);
128 24 : if (sobj == NULL)
129 : {
130 : /* If we get an error here, just pretend that we didn't find any
131 : export data. This is the right thing to do if the error is
132 : that the file was not recognized as an object file. This
133 : will ignore file I/O errors, but it's not too big a deal
134 : because we will wind up giving some other error later. */
135 : return NULL;
136 : }
137 :
138 0 : found = simple_object_find_section (sobj, RUST_EXPORT_SECTION_NAME,
139 : &sec_offset, &sec_length, &errmsg, perr);
140 0 : simple_object_release_read (sobj);
141 0 : if (!found)
142 0 : return errmsg;
143 :
144 0 : if (lseek (fd, offset + sec_offset, SEEK_SET) < 0)
145 : {
146 0 : *perr = errno;
147 0 : return _ ("lseek failed while reading export data");
148 : }
149 :
150 0 : buf = XNEWVEC (char, sec_length);
151 0 : if (buf == NULL)
152 : {
153 : *perr = errno;
154 : return _ ("memory allocation failed while reading export data");
155 : }
156 :
157 0 : c = read (fd, buf, sec_length);
158 0 : if (c < 0)
159 : {
160 0 : *perr = errno;
161 0 : free (buf);
162 0 : return _ ("read failed while reading export data");
163 : }
164 :
165 0 : if (c < sec_length)
166 : {
167 0 : free (buf);
168 0 : return _ ("short read while reading export data");
169 : }
170 :
171 0 : *pbuf = buf;
172 0 : *plen = sec_length;
173 :
174 0 : return NULL;
175 : }
|