@@ -10,7 +10,69 @@ use core::cmp;
10
10
use core:: fmt;
11
11
12
12
use crate :: bindings;
13
- use crate :: c_types:: c_int;
13
+ use crate :: c_types:: { c_char, c_int, c_void} ;
14
+
15
+ // Called from vsprintf with format specifier %pfr.
16
+ #[ no_mangle]
17
+ unsafe fn rust_fmt_argument (
18
+ buf : * mut c_char ,
19
+ end : * mut c_char ,
20
+ ptr : * const c_void ,
21
+ limit : c_int ,
22
+ ) -> * mut c_char {
23
+ use fmt:: Write ;
24
+
25
+ // Use `usize` to use saturating_* functions.
26
+ struct Writer {
27
+ buf : usize ,
28
+ end : usize ,
29
+ limit : usize ,
30
+ }
31
+
32
+ impl Write for Writer {
33
+ fn write_str ( & mut self , s : & str ) -> fmt:: Result {
34
+ // Maximum possible length to write, bounded by limit.
35
+ let len = cmp:: min ( s. len ( ) , self . limit ) ;
36
+
37
+ // `buf` value after writing `len` bytes. This does not have to be bounded
38
+ // by `end`, but we don't want it to wrap around to 0.
39
+ let buf_new = self . buf . saturating_add ( len) ;
40
+
41
+ // Amount that we can copy. `saturating_sub` ensures we get 0 if
42
+ // `buf` goes past `end`.
43
+ let len_to_copy = cmp:: min ( buf_new, self . end ) . saturating_sub ( self . buf ) ;
44
+
45
+ // SAFETY: In any case, `buf` is non-null and properly aligned.
46
+ // If `len_to_copy` is non-zero, then we know `buf` has not past
47
+ // `end` yet and so is valid.
48
+ unsafe {
49
+ core:: ptr:: copy_nonoverlapping (
50
+ s. as_bytes ( ) . as_ptr ( ) ,
51
+ self . buf as * mut u8 ,
52
+ len_to_copy,
53
+ )
54
+ } ;
55
+
56
+ self . buf = buf_new;
57
+ if s. len ( ) <= self . limit {
58
+ self . limit -= s. len ( ) ;
59
+ Ok ( ( ) )
60
+ } else {
61
+ Err ( fmt:: Error )
62
+ }
63
+ }
64
+ }
65
+
66
+ let mut w = Writer {
67
+ buf : buf as _ ,
68
+ end : end as _ ,
69
+ // On C-side, unlimited is represented as -1, this cast will change it
70
+ // to usize::MAX, which serves the same purpose.
71
+ limit : limit as _ ,
72
+ } ;
73
+ let _ = w. write_fmt ( * ( ptr as * const fmt:: Arguments ) ) ;
74
+ w. buf as _
75
+ }
14
76
15
77
/// Format strings.
16
78
///
@@ -42,9 +104,9 @@ pub mod format_strings {
42
104
assert ! ( prefix[ 2 ] == b'\x00' ) ;
43
105
44
106
let suffix: & [ u8 ; LENGTH - LENGTH_PREFIX ] = if is_cont {
45
- b"%.*s \0 \0 \0 \0 \0 "
107
+ b"%pfr \0 \0 \0 \0 \0 "
46
108
} else {
47
- b"%s: %.*s \0 "
109
+ b"%s: %pfr \0 "
48
110
} ;
49
111
50
112
[
@@ -84,14 +146,13 @@ pub mod format_strings {
84
146
pub unsafe fn call_printk (
85
147
format_string : & [ u8 ; format_strings:: LENGTH ] ,
86
148
module_name : & [ u8 ] ,
87
- string : & [ u8 ] ,
149
+ args : fmt :: Arguments ,
88
150
) {
89
151
// `printk` does not seem to fail in any path.
90
152
bindings:: printk (
91
153
format_string. as_ptr ( ) as _ ,
92
154
module_name. as_ptr ( ) ,
93
- string. len ( ) as c_int ,
94
- string. as_ptr ( ) ,
155
+ & args as * const _ as * const c_void ,
95
156
) ;
96
157
}
97
158
@@ -101,112 +162,25 @@ pub unsafe fn call_printk(
101
162
///
102
163
/// [`printk`]: ../../../../include/linux/printk.h
103
164
#[ doc( hidden) ]
104
- pub fn call_printk_cont ( string : & [ u8 ] ) {
165
+ pub fn call_printk_cont ( args : fmt :: Arguments ) {
105
166
// `printk` does not seem to fail in any path.
106
167
//
107
168
// SAFETY: The format string is fixed.
108
169
unsafe {
109
170
bindings:: printk (
110
171
format_strings:: CONT . as_ptr ( ) as _ ,
111
- string. len ( ) as c_int ,
112
- string. as_ptr ( ) ,
172
+ & args as * const _ as * const c_void ,
113
173
) ;
114
174
}
115
175
}
116
176
117
- /// The maximum size of a log line in the kernel.
118
- ///
119
- /// From `kernel/printk/printk.c`.
120
- const LOG_LINE_MAX : usize = 1024 - 32 ;
121
-
122
- /// The maximum size of a log line in our side.
123
- ///
124
- /// FIXME: We should be smarter than this, but for the moment, to reduce stack
125
- /// usage, we only allow this much which should work for most purposes.
126
- const LOG_LINE_SIZE : usize = 300 ;
127
- crate :: static_assert!( LOG_LINE_SIZE <= LOG_LINE_MAX ) ;
128
-
129
- /// Public but hidden since it should only be used from public macros.
130
- #[ doc( hidden) ]
131
- pub struct LogLineWriter {
132
- data : [ u8 ; LOG_LINE_SIZE ] ,
133
- pos : usize ,
134
- }
135
-
136
- impl LogLineWriter {
137
- /// Creates a new [`LogLineWriter`].
138
- pub fn new ( ) -> LogLineWriter {
139
- LogLineWriter {
140
- data : [ 0u8 ; LOG_LINE_SIZE ] ,
141
- pos : 0 ,
142
- }
143
- }
144
-
145
- /// Returns the internal buffer as a byte slice.
146
- pub fn as_bytes ( & self ) -> & [ u8 ] {
147
- & self . data [ ..self . pos ]
148
- }
149
- }
150
-
151
- impl Default for LogLineWriter {
152
- fn default ( ) -> Self {
153
- Self :: new ( )
154
- }
155
- }
156
-
157
- impl fmt:: Write for LogLineWriter {
158
- fn write_str ( & mut self , s : & str ) -> fmt:: Result {
159
- let copy_len = cmp:: min ( LOG_LINE_SIZE - self . pos , s. as_bytes ( ) . len ( ) ) ;
160
- self . data [ self . pos ..self . pos + copy_len] . copy_from_slice ( & s. as_bytes ( ) [ ..copy_len] ) ;
161
- self . pos += copy_len;
162
- Ok ( ( ) )
163
- }
164
- }
165
-
166
- /// Helper function for the [`print_macro!`] to reduce stack usage.
167
- ///
168
- /// Public but hidden since it should only be used from public macros.
169
- ///
170
- /// # Safety
171
- ///
172
- /// The format string must be one of the ones in [`format_strings`], and
173
- /// the module name must be null-terminated.
174
- #[ doc( hidden) ]
175
- pub unsafe fn format_and_call < const CONT : bool > (
176
- format_string : & [ u8 ; format_strings:: LENGTH ] ,
177
- module_name : & [ u8 ] ,
178
- args : fmt:: Arguments ,
179
- ) {
180
- // Careful: this object takes quite a bit of stack.
181
- let mut writer = LogLineWriter :: new ( ) ;
182
-
183
- match fmt:: write ( & mut writer, args) {
184
- Ok ( _) => {
185
- if CONT {
186
- call_printk_cont ( writer. as_bytes ( ) ) ;
187
- } else {
188
- call_printk ( format_string, module_name, writer. as_bytes ( ) ) ;
189
- }
190
- }
191
-
192
- Err ( _) => {
193
- call_printk (
194
- & format_strings:: CRIT ,
195
- module_name,
196
- b"Failure to format string.\n " ,
197
- ) ;
198
- }
199
- } ;
200
- }
201
-
202
177
/// Performs formatting and forwards the string to [`call_printk`].
203
178
///
204
179
/// Public but hidden since it should only be used from public macros.
205
180
#[ doc( hidden) ]
206
181
#[ macro_export]
207
182
macro_rules! print_macro (
208
- // Without extra arguments: no need to format anything.
209
- ( $format_string: path, false , $fmt: expr) => (
183
+ ( $format_string: path, false , $( $arg: tt) +) => (
210
184
// SAFETY: This hidden macro should only be called by the documented
211
185
// printing macros which ensure the format string is one of the fixed
212
186
// ones. All `__LOG_PREFIX`s are null-terminated as they are generated
@@ -216,47 +190,17 @@ macro_rules! print_macro (
216
190
$crate:: print:: call_printk(
217
191
& $format_string,
218
192
crate :: __LOG_PREFIX,
219
- $fmt . as_bytes ( ) ,
193
+ format_args! ( $ ( $arg ) + ) ,
220
194
) ;
221
195
}
222
196
) ;
223
197
224
- // Without extra arguments: no need to format anything (`CONT` case).
225
- ( $format_string: path, true , $fmt : expr ) => (
198
+ // (`CONT` case).
199
+ ( $format_string: path, true , $( $arg : tt ) + ) => (
226
200
$crate:: print:: call_printk_cont(
227
- $fmt . as_bytes ( ) ,
201
+ format_args! ( $ ( $arg ) + ) ,
228
202
) ;
229
203
) ;
230
-
231
- // With extra arguments: we need to perform formatting.
232
- ( $format_string: path, $cont: literal, $fmt: expr, $( $arg: tt) * ) => (
233
- // Forwarding the call to a function to perform the formatting
234
- // is needed here to avoid stack overflows in non-optimized builds when
235
- // invoking the printing macros a lot of times in the same function.
236
- // Without it, the compiler reserves one `LogLineWriter` per macro
237
- // invocation, which is a huge type.
238
- //
239
- // We could use an immediately-invoked closure for this, which
240
- // seems to lower even more the stack usage at `opt-level=0` because
241
- // `fmt::Arguments` objects do not pile up. However, that breaks
242
- // the `?` operator if used in one of the arguments.
243
- //
244
- // At `opt-level=2`, the generated code is basically the same for
245
- // all alternatives.
246
- //
247
- // SAFETY: This hidden macro should only be called by the documented
248
- // printing macros which ensure the format string is one of the fixed
249
- // ones. All `__LOG_PREFIX`s are null-terminated as they are generated
250
- // by the `module!` proc macro or fixed values defined in a kernel
251
- // crate.
252
- unsafe {
253
- $crate:: print:: format_and_call:: <$cont>(
254
- & $format_string,
255
- crate :: __LOG_PREFIX,
256
- format_args!( $fmt, $( $arg) * ) ,
257
- ) ;
258
- }
259
- ) ;
260
204
) ;
261
205
262
206
// We could use a macro to generate these macros. However, doing so ends
0 commit comments