Branch data Line data Source code
1 : : /* Copyright (C) 2010-2025 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 : 48707 : saw_errors (void)
56 : : {
57 : 48707 : 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 : 16 : rust_read_export_data (int fd, off_t offset, char **pbuf, size_t *plen,
113 : : int *perr)
114 : : {
115 : 16 : simple_object_read *sobj;
116 : 16 : const char *errmsg;
117 : 16 : off_t sec_offset;
118 : 16 : off_t sec_length;
119 : 16 : int found;
120 : 16 : char *buf;
121 : 16 : ssize_t c;
122 : :
123 : 16 : *pbuf = NULL;
124 : 16 : *plen = 0;
125 : :
126 : 16 : sobj = simple_object_start_read (fd, offset, RUST_EXPORT_SEGMENT_NAME,
127 : : &errmsg, perr);
128 : 16 : 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 : : }
|