1*5225e6b1SAndroid Build Coastguard Worker // Copyright 2023-2024, The Android Open Source Project
2*5225e6b1SAndroid Build Coastguard Worker //
3*5225e6b1SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*5225e6b1SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*5225e6b1SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*5225e6b1SAndroid Build Coastguard Worker //
7*5225e6b1SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
8*5225e6b1SAndroid Build Coastguard Worker //
9*5225e6b1SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*5225e6b1SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*5225e6b1SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*5225e6b1SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*5225e6b1SAndroid Build Coastguard Worker // limitations under the License.
14*5225e6b1SAndroid Build Coastguard Worker
15*5225e6b1SAndroid Build Coastguard Worker //! This library provides implementation for a few libc functions for building third party C
16*5225e6b1SAndroid Build Coastguard Worker //! libraries.
17*5225e6b1SAndroid Build Coastguard Worker
18*5225e6b1SAndroid Build Coastguard Worker #![cfg_attr(not(test), no_std)]
19*5225e6b1SAndroid Build Coastguard Worker
20*5225e6b1SAndroid Build Coastguard Worker extern crate alloc;
21*5225e6b1SAndroid Build Coastguard Worker
22*5225e6b1SAndroid Build Coastguard Worker use alloc::alloc::{alloc, dealloc};
23*5225e6b1SAndroid Build Coastguard Worker use core::{
24*5225e6b1SAndroid Build Coastguard Worker alloc::Layout,
25*5225e6b1SAndroid Build Coastguard Worker ffi::{c_char, c_int, c_ulong, c_void},
26*5225e6b1SAndroid Build Coastguard Worker mem::size_of_val,
27*5225e6b1SAndroid Build Coastguard Worker ptr::{null_mut, NonNull},
28*5225e6b1SAndroid Build Coastguard Worker };
29*5225e6b1SAndroid Build Coastguard Worker use safemath::SafeNum;
30*5225e6b1SAndroid Build Coastguard Worker
31*5225e6b1SAndroid Build Coastguard Worker pub use strcmp::{strcmp, strncmp};
32*5225e6b1SAndroid Build Coastguard Worker
33*5225e6b1SAndroid Build Coastguard Worker pub mod strchr;
34*5225e6b1SAndroid Build Coastguard Worker pub mod strcmp;
35*5225e6b1SAndroid Build Coastguard Worker pub mod strtoul;
36*5225e6b1SAndroid Build Coastguard Worker
37*5225e6b1SAndroid Build Coastguard Worker // Linking compiler built-in intrinsics to expose libc compatible implementations
38*5225e6b1SAndroid Build Coastguard Worker // https://cs.android.com/android/platform/superproject/main/+/2e15fc2eadcb7db07bf6656086c50153bbafe7b6:prebuilts/rust/linux-x86/1.78.0/lib/rustlib/src/rust/vendor/compiler_builtins/src/mem/mod.rs;l=22
39*5225e6b1SAndroid Build Coastguard Worker extern "C" {
40*5225e6b1SAndroid Build Coastguard Worker /// int memcmp(const void *src1, const void *src2, size_t n)
memcmp(src1: *const c_void, src2: *const c_void, n: usize) -> c_int41*5225e6b1SAndroid Build Coastguard Worker pub fn memcmp(src1: *const c_void, src2: *const c_void, n: usize) -> c_int;
42*5225e6b1SAndroid Build Coastguard Worker /// void *memset(void *dest, int c, size_t n)
memset(dest: *mut c_void, c: c_int, n: usize) -> *mut c_void43*5225e6b1SAndroid Build Coastguard Worker pub fn memset(dest: *mut c_void, c: c_int, n: usize) -> *mut c_void;
44*5225e6b1SAndroid Build Coastguard Worker /// void *memcpy(void *dest, const void *src, size_t n)
memcpy(dest: *mut c_void, src: *const c_void, n: usize) -> *mut c_void45*5225e6b1SAndroid Build Coastguard Worker pub fn memcpy(dest: *mut c_void, src: *const c_void, n: usize) -> *mut c_void;
46*5225e6b1SAndroid Build Coastguard Worker /// size_t strlen(const char *s)
strlen(s: *const c_char) -> usize47*5225e6b1SAndroid Build Coastguard Worker pub fn strlen(s: *const c_char) -> usize;
48*5225e6b1SAndroid Build Coastguard Worker }
49*5225e6b1SAndroid Build Coastguard Worker
50*5225e6b1SAndroid Build Coastguard Worker /// Extended version of void *malloc(size_t size) with ptr alignment configuration support.
51*5225e6b1SAndroid Build Coastguard Worker /// Libraries may have a different alignment requirements.
52*5225e6b1SAndroid Build Coastguard Worker ///
53*5225e6b1SAndroid Build Coastguard Worker /// # Safety
54*5225e6b1SAndroid Build Coastguard Worker ///
55*5225e6b1SAndroid Build Coastguard Worker /// * Returns a valid pointer to a memory block of `size` bytes, aligned to `alignment`, or null
56*5225e6b1SAndroid Build Coastguard Worker /// on failure.
57*5225e6b1SAndroid Build Coastguard Worker #[no_mangle]
gbl_malloc(request_size: usize, alignment: usize) -> *mut c_void58*5225e6b1SAndroid Build Coastguard Worker pub unsafe extern "C" fn gbl_malloc(request_size: usize, alignment: usize) -> *mut c_void {
59*5225e6b1SAndroid Build Coastguard Worker (|| {
60*5225e6b1SAndroid Build Coastguard Worker // Prefix data:
61*5225e6b1SAndroid Build Coastguard Worker let mut size = 0usize;
62*5225e6b1SAndroid Build Coastguard Worker let mut offset = 0usize;
63*5225e6b1SAndroid Build Coastguard Worker
64*5225e6b1SAndroid Build Coastguard Worker // Determine prefix size necessary to store data required for [gbl_free]: size, offset
65*5225e6b1SAndroid Build Coastguard Worker let prefix_size: usize = size_of_val(&size) + size_of_val(&offset);
66*5225e6b1SAndroid Build Coastguard Worker
67*5225e6b1SAndroid Build Coastguard Worker // Determine padding necessary to guarantee alignment. Padding includes prefix data.
68*5225e6b1SAndroid Build Coastguard Worker let pad: usize = (SafeNum::from(alignment) + prefix_size).try_into().ok()?;
69*5225e6b1SAndroid Build Coastguard Worker
70*5225e6b1SAndroid Build Coastguard Worker // Actual size to allocate. It includes padding to guarantee alignment.
71*5225e6b1SAndroid Build Coastguard Worker size = (SafeNum::from(request_size) + pad).try_into().ok()?;
72*5225e6b1SAndroid Build Coastguard Worker
73*5225e6b1SAndroid Build Coastguard Worker // SAFETY:
74*5225e6b1SAndroid Build Coastguard Worker // * On success, `alloc` guarantees to allocate enough memory.
75*5225e6b1SAndroid Build Coastguard Worker let ptr = unsafe {
76*5225e6b1SAndroid Build Coastguard Worker // Due to manual aligning, there is no need for specific layout alignment.
77*5225e6b1SAndroid Build Coastguard Worker NonNull::new(alloc(Layout::from_size_align(size, 1).ok()?))?.as_ptr()
78*5225e6b1SAndroid Build Coastguard Worker };
79*5225e6b1SAndroid Build Coastguard Worker
80*5225e6b1SAndroid Build Coastguard Worker // Calculate the aligned address to return the caller.
81*5225e6b1SAndroid Build Coastguard Worker let ret_address = (SafeNum::from(ptr as usize) + prefix_size).round_up(alignment);
82*5225e6b1SAndroid Build Coastguard Worker
83*5225e6b1SAndroid Build Coastguard Worker // Calculate the offsets from the allocation start.
84*5225e6b1SAndroid Build Coastguard Worker let ret_offset = ret_address - (ptr as usize);
85*5225e6b1SAndroid Build Coastguard Worker let align_offset: usize = (ret_offset - size_of_val(&size)).try_into().ok()?;
86*5225e6b1SAndroid Build Coastguard Worker let size_offset: usize = (align_offset - size_of_val(&offset)).try_into().ok()?;
87*5225e6b1SAndroid Build Coastguard Worker offset = usize::try_from(ret_offset).ok()?;
88*5225e6b1SAndroid Build Coastguard Worker
89*5225e6b1SAndroid Build Coastguard Worker // SAFETY:
90*5225e6b1SAndroid Build Coastguard Worker // 'ptr' is guarantied to be valid:
91*5225e6b1SAndroid Build Coastguard Worker // - not NULL; Checked with `NonNull`
92*5225e6b1SAndroid Build Coastguard Worker // - it points to single block of memory big enough to hold size+offset (allocated this
93*5225e6b1SAndroid Build Coastguard Worker // way)
94*5225e6b1SAndroid Build Coastguard Worker // - memory is 1-byte aligned for [u8] slice
95*5225e6b1SAndroid Build Coastguard Worker // - ptr+offset is guarantied to point to the buffer of size 'size' as per allocation that
96*5225e6b1SAndroid Build Coastguard Worker // takes into account padding and prefix.
97*5225e6b1SAndroid Build Coastguard Worker unsafe {
98*5225e6b1SAndroid Build Coastguard Worker // Write metadata and return the caller's pointer.
99*5225e6b1SAndroid Build Coastguard Worker core::slice::from_raw_parts_mut(ptr.add(size_offset), size_of_val(&size))
100*5225e6b1SAndroid Build Coastguard Worker .copy_from_slice(&size.to_ne_bytes());
101*5225e6b1SAndroid Build Coastguard Worker core::slice::from_raw_parts_mut(ptr.add(align_offset), size_of_val(&offset))
102*5225e6b1SAndroid Build Coastguard Worker .copy_from_slice(&offset.to_ne_bytes());
103*5225e6b1SAndroid Build Coastguard Worker
104*5225e6b1SAndroid Build Coastguard Worker Some(ptr.add(offset))
105*5225e6b1SAndroid Build Coastguard Worker }
106*5225e6b1SAndroid Build Coastguard Worker })()
107*5225e6b1SAndroid Build Coastguard Worker .unwrap_or(null_mut()) as _
108*5225e6b1SAndroid Build Coastguard Worker }
109*5225e6b1SAndroid Build Coastguard Worker
110*5225e6b1SAndroid Build Coastguard Worker /// Extended version of void free(void *ptr) with ptr alignment configuration support.
111*5225e6b1SAndroid Build Coastguard Worker ///
112*5225e6b1SAndroid Build Coastguard Worker /// # Safety
113*5225e6b1SAndroid Build Coastguard Worker ///
114*5225e6b1SAndroid Build Coastguard Worker /// * `ptr` must be allocated by `gbl_malloc` and guarantee enough memory for a preceding
115*5225e6b1SAndroid Build Coastguard Worker /// `usize` value and payload or null.
116*5225e6b1SAndroid Build Coastguard Worker /// * `gbl_free` must be called with the same `alignment` as the corresponding `gbl_malloc` call.
117*5225e6b1SAndroid Build Coastguard Worker #[no_mangle]
gbl_free(ptr: *mut c_void, alignment: usize)118*5225e6b1SAndroid Build Coastguard Worker pub unsafe extern "C" fn gbl_free(ptr: *mut c_void, alignment: usize) {
119*5225e6b1SAndroid Build Coastguard Worker if ptr.is_null() {
120*5225e6b1SAndroid Build Coastguard Worker // follow libc free behavior
121*5225e6b1SAndroid Build Coastguard Worker return;
122*5225e6b1SAndroid Build Coastguard Worker }
123*5225e6b1SAndroid Build Coastguard Worker let mut ptr = ptr as *mut u8;
124*5225e6b1SAndroid Build Coastguard Worker
125*5225e6b1SAndroid Build Coastguard Worker let mut offset = 0usize;
126*5225e6b1SAndroid Build Coastguard Worker let mut size = 0usize;
127*5225e6b1SAndroid Build Coastguard Worker
128*5225e6b1SAndroid Build Coastguard Worker // Calculate offsets for size of align data
129*5225e6b1SAndroid Build Coastguard Worker let align_offset: usize = size_of_val(&size);
130*5225e6b1SAndroid Build Coastguard Worker let size_offset: usize = align_offset + size_of_val(&size);
131*5225e6b1SAndroid Build Coastguard Worker
132*5225e6b1SAndroid Build Coastguard Worker // Read size used in allocation from prefix data.
133*5225e6b1SAndroid Build Coastguard Worker offset = usize::from_ne_bytes(
134*5225e6b1SAndroid Build Coastguard Worker // SAFETY:
135*5225e6b1SAndroid Build Coastguard Worker // * `ptr` is allocated by `gbl_malloc` and has enough padding before `ptr` to hold
136*5225e6b1SAndroid Build Coastguard Worker // prefix data. Which consists of align and size values.
137*5225e6b1SAndroid Build Coastguard Worker // * Alignment is 1 for &[u8]
138*5225e6b1SAndroid Build Coastguard Worker unsafe { core::slice::from_raw_parts(ptr.sub(align_offset), size_of_val(&offset)) }
139*5225e6b1SAndroid Build Coastguard Worker .try_into()
140*5225e6b1SAndroid Build Coastguard Worker .unwrap(),
141*5225e6b1SAndroid Build Coastguard Worker );
142*5225e6b1SAndroid Build Coastguard Worker
143*5225e6b1SAndroid Build Coastguard Worker // Read offset for unaligned pointer from prefix data.
144*5225e6b1SAndroid Build Coastguard Worker size = usize::from_ne_bytes(
145*5225e6b1SAndroid Build Coastguard Worker // SAFETY:
146*5225e6b1SAndroid Build Coastguard Worker // * `ptr` is allocated by `gbl_malloc` and has enough padding before `ptr` to hold
147*5225e6b1SAndroid Build Coastguard Worker // prefix data. Which consists of align and size values.
148*5225e6b1SAndroid Build Coastguard Worker // * Alignment is 1 for &[u8]
149*5225e6b1SAndroid Build Coastguard Worker unsafe { core::slice::from_raw_parts(ptr.sub(size_offset), size_of_val(&size)) }
150*5225e6b1SAndroid Build Coastguard Worker .try_into()
151*5225e6b1SAndroid Build Coastguard Worker .unwrap(),
152*5225e6b1SAndroid Build Coastguard Worker );
153*5225e6b1SAndroid Build Coastguard Worker
154*5225e6b1SAndroid Build Coastguard Worker // SAFETY:
155*5225e6b1SAndroid Build Coastguard Worker // * `ptr` is allocated by `gbl_malloc` and has enough padding before `ptr` to hold
156*5225e6b1SAndroid Build Coastguard Worker // prefix data. ptr - offset must point to unaligned pointer to buffer, which was returned by
157*5225e6b1SAndroid Build Coastguard Worker // `alloc`, and must be passed to `dealloc`
158*5225e6b1SAndroid Build Coastguard Worker unsafe {
159*5225e6b1SAndroid Build Coastguard Worker // Calculate unaligned pointer returned by [alloc], which must be used in [dealloc]
160*5225e6b1SAndroid Build Coastguard Worker ptr = ptr.sub(offset);
161*5225e6b1SAndroid Build Coastguard Worker
162*5225e6b1SAndroid Build Coastguard Worker // Call to global allocator.
163*5225e6b1SAndroid Build Coastguard Worker dealloc(ptr, Layout::from_size_align(size, alignment).unwrap());
164*5225e6b1SAndroid Build Coastguard Worker };
165*5225e6b1SAndroid Build Coastguard Worker }
166*5225e6b1SAndroid Build Coastguard Worker
167*5225e6b1SAndroid Build Coastguard Worker /// void *memchr(const void *ptr, int ch, size_t count);
168*5225e6b1SAndroid Build Coastguard Worker ///
169*5225e6b1SAndroid Build Coastguard Worker /// # Safety
170*5225e6b1SAndroid Build Coastguard Worker ///
171*5225e6b1SAndroid Build Coastguard Worker /// * `ptr` needs to be a buffer with at least `count` bytes.
172*5225e6b1SAndroid Build Coastguard Worker /// * Returns the pointer within `ptr` buffer, or null if not found.
173*5225e6b1SAndroid Build Coastguard Worker #[no_mangle]
memchr(ptr: *const c_void, ch: c_int, count: c_ulong) -> *mut c_void174*5225e6b1SAndroid Build Coastguard Worker pub unsafe extern "C" fn memchr(ptr: *const c_void, ch: c_int, count: c_ulong) -> *mut c_void {
175*5225e6b1SAndroid Build Coastguard Worker assert!(!ptr.is_null());
176*5225e6b1SAndroid Build Coastguard Worker let start = ptr as *const u8;
177*5225e6b1SAndroid Build Coastguard Worker let target = (ch & 0xff) as u8;
178*5225e6b1SAndroid Build Coastguard Worker for i in 0..count {
179*5225e6b1SAndroid Build Coastguard Worker // SAFETY: `ptr` buffer is assumed valid and bounded by count.
180*5225e6b1SAndroid Build Coastguard Worker let curr = unsafe { start.add(i.try_into().unwrap()) };
181*5225e6b1SAndroid Build Coastguard Worker // SAFETY: `ptr` buffer is assumed valid and bounded by count.
182*5225e6b1SAndroid Build Coastguard Worker if *unsafe { curr.as_ref().unwrap() } == target {
183*5225e6b1SAndroid Build Coastguard Worker return curr as *mut _;
184*5225e6b1SAndroid Build Coastguard Worker }
185*5225e6b1SAndroid Build Coastguard Worker }
186*5225e6b1SAndroid Build Coastguard Worker null_mut()
187*5225e6b1SAndroid Build Coastguard Worker }
188*5225e6b1SAndroid Build Coastguard Worker
189*5225e6b1SAndroid Build Coastguard Worker /// size_t strnlen(const char *s, size_t maxlen);
190*5225e6b1SAndroid Build Coastguard Worker ///
191*5225e6b1SAndroid Build Coastguard Worker /// # Safety
192*5225e6b1SAndroid Build Coastguard Worker ///
193*5225e6b1SAndroid Build Coastguard Worker /// * `s` must be a valid pointer to a null terminated C string.
194*5225e6b1SAndroid Build Coastguard Worker #[no_mangle]
strnlen(s: *const c_char, maxlen: usize) -> usize195*5225e6b1SAndroid Build Coastguard Worker pub unsafe extern "C" fn strnlen(s: *const c_char, maxlen: usize) -> usize {
196*5225e6b1SAndroid Build Coastguard Worker // SAFETY: `s` is a valid pointer to a null terminated string.
197*5225e6b1SAndroid Build Coastguard Worker match unsafe { memchr(s as *const _, 0, maxlen.try_into().unwrap()) } {
198*5225e6b1SAndroid Build Coastguard Worker p if p.is_null() => maxlen,
199*5225e6b1SAndroid Build Coastguard Worker p => (p as usize) - (s as usize),
200*5225e6b1SAndroid Build Coastguard Worker }
201*5225e6b1SAndroid Build Coastguard Worker }
202