1 /* ld.so error exception allocation and deallocation.
2 Copyright (C) 1995-2023 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
28 /* This message we return as a last resort. We define the string in a
29 variable since we have to avoid freeing it and so have to enable
30 a pointer comparison. See below and in dlfcn/dlerror.c. */
31 static const char _dl_out_of_memory
[] = "out of memory";
33 /* Call free in the main libc.so. This allows other namespaces to
34 free pointers on the main libc heap, via GLRO (dl_error_free). It
35 also avoids calling free on the special, pre-allocated
36 out-of-memory error message. */
38 _dl_error_free (void *ptr
)
40 if (ptr
!= _dl_out_of_memory
)
44 /* Dummy allocation object used if allocating the message buffer
47 oom_exception (struct dl_exception
*exception
)
49 exception
->objname
= "";
50 exception
->errstring
= _dl_out_of_memory
;
51 exception
->message_buffer
= NULL
;
55 __attribute__ ((noreturn
))
56 length_mismatch (void)
58 _dl_fatal_printf ("Fatal error: "
59 "length accounting in _dl_exception_create_format\n");
62 /* Adjust the message buffer to indicate whether it is possible to
63 free it. EXCEPTION->errstring must be a potentially deallocatable
66 adjust_message_buffer (struct dl_exception
*exception
)
68 /* If the main executable is relocated it means the libc's malloc
72 malloced
= (GL(dl_ns
)[LM_ID_BASE
]._ns_loaded
!= NULL
73 && (GL(dl_ns
)[LM_ID_BASE
]._ns_loaded
->l_relocated
!= 0));
76 exception
->message_buffer
= (char *) exception
->errstring
;
78 exception
->message_buffer
= NULL
;
82 _dl_exception_create (struct dl_exception
*exception
, const char *objname
,
83 const char *errstring
)
87 size_t len_objname
= strlen (objname
) + 1;
88 size_t len_errstring
= strlen (errstring
) + 1;
89 char *errstring_copy
= malloc (len_objname
+ len_errstring
);
90 if (errstring_copy
!= NULL
)
92 /* Make a copy of the object file name and the error string. */
93 exception
->objname
= memcpy (__mempcpy (errstring_copy
,
94 errstring
, len_errstring
),
95 objname
, len_objname
);
96 exception
->errstring
= errstring_copy
;
97 adjust_message_buffer (exception
);
100 oom_exception (exception
);
102 rtld_hidden_def (_dl_exception_create
)
105 _dl_exception_create_format (struct dl_exception
*exception
, const char *objname
,
106 const char *fmt
, ...)
110 size_t len_objname
= strlen (objname
) + 1;
111 /* Compute the length of the result. Include room for two NUL
113 size_t length
= len_objname
+ 1;
117 for (const char *p
= fmt
; *p
!= '\0'; ++p
)
124 length
+= strlen (va_arg (ap
, const char *));
126 /* Recognize the l modifier. It is only important on some
127 platforms where long and int have a different size. We
128 can use the same code for size_t. */
133 length
+= LONG_WIDTH
/ 4;
139 length
+= INT_WIDTH
/ 4;
142 /* Assumed to be '%'. */
152 if (length
> PTRDIFF_MAX
)
154 oom_exception (exception
);
157 char *errstring
= malloc (length
);
158 if (errstring
== NULL
)
160 oom_exception (exception
);
163 exception
->errstring
= errstring
;
164 adjust_message_buffer (exception
);
166 /* Copy the error message to errstring. */
168 /* Next byte to be written in errstring. */
169 char *wptr
= errstring
;
170 /* End of the allocated string. */
171 char *const end
= errstring
+ length
;
176 for (const char *p
= fmt
; *p
!= '\0'; ++p
)
184 const char *ptr
= va_arg (ap
, const char *);
185 size_t len_ptr
= strlen (ptr
);
186 if (len_ptr
> end
- wptr
)
188 wptr
= __mempcpy (wptr
, ptr
, len_ptr
);
199 unsigned long int num
= va_arg (ap
, unsigned int);
201 wptr
+= INT_WIDTH
/ 4;
202 char *cp
= _itoa (num
, wptr
, 16, 0);
203 /* Pad to the full width with 0. */
212 unsigned long int num
= va_arg (ap
, unsigned long int);
214 wptr
+= LONG_WIDTH
/ 4;
215 char *cp
= _itoa (num
, wptr
, 16, 0);
216 /* Pad to the full width with 0. */
224 _dl_fatal_printf ("Fatal error:"
225 " invalid format in exception string\n");
240 if (len_objname
!= end
- wptr
)
242 exception
->objname
= memcpy (wptr
, objname
, len_objname
);
246 rtld_hidden_def (_dl_exception_create_format
)
249 _dl_exception_free (struct dl_exception
*exception
)
251 free (exception
->message_buffer
);
252 exception
->objname
= NULL
;
253 exception
->errstring
= NULL
;
254 exception
->message_buffer
= NULL
;
256 rtld_hidden_def (_dl_exception_free
)