]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/processor-trace/libipt/test/src/ptunit-section.c
Update to Zstandard 1.4.0
[FreeBSD/FreeBSD.git] / contrib / processor-trace / libipt / test / src / ptunit-section.c
1 /*
2  * Copyright (c) 2013-2018, Intel Corporation
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *  * Redistributions of source code must retain the above copyright notice,
8  *    this list of conditions and the following disclaimer.
9  *  * Redistributions in binary form must reproduce the above copyright notice,
10  *    this list of conditions and the following disclaimer in the documentation
11  *    and/or other materials provided with the distribution.
12  *  * Neither the name of Intel Corporation nor the names of its contributors
13  *    may be used to endorse or promote products derived from this software
14  *    without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "ptunit_threads.h"
30 #include "ptunit_mkfile.h"
31
32 #include "pt_section.h"
33 #include "pt_block_cache.h"
34
35 #include "intel-pt.h"
36
37 #include <stdlib.h>
38 #include <stdio.h>
39
40
41
42 struct pt_image_section_cache {
43         int map;
44 };
45
46 extern int pt_iscache_notify_map(struct pt_image_section_cache *iscache,
47                                  struct pt_section *section);
48 extern int pt_iscache_notify_resize(struct pt_image_section_cache *iscache,
49                                     struct pt_section *section, uint64_t size);
50
51 int pt_iscache_notify_map(struct pt_image_section_cache *iscache,
52                           struct pt_section *section)
53 {
54         if (!iscache)
55                 return -pte_internal;
56
57         if (iscache->map <= 0)
58                 return iscache->map;
59
60         /* Avoid recursion. */
61         iscache->map = 0;
62
63         return pt_section_map_share(section);
64 }
65
66 int pt_iscache_notify_resize(struct pt_image_section_cache *iscache,
67                              struct pt_section *section, uint64_t size)
68 {
69         uint64_t memsize;
70         int errcode;
71
72         if (!iscache)
73                 return -pte_internal;
74
75         if (iscache->map <= 0)
76                 return iscache->map;
77
78         /* Avoid recursion. */
79         iscache->map = 0;
80
81         errcode = pt_section_memsize(section, &memsize);
82         if (errcode < 0)
83                 return errcode;
84
85         if (size != memsize)
86                 return -pte_internal;
87
88         return pt_section_map_share(section);
89 }
90
91 struct pt_block_cache *pt_bcache_alloc(uint64_t nentries)
92 {
93         struct pt_block_cache *bcache;
94
95         if (!nentries || (UINT32_MAX < nentries))
96                 return NULL;
97
98         /* The cache is not really used by tests.  It suffices to allocate only
99          * the cache struct with the single default entry.
100          *
101          * We still set the number of entries to the requested size.
102          */
103         bcache = malloc(sizeof(*bcache));
104         if (bcache)
105                 bcache->nentries = (uint32_t) nentries;
106
107         return bcache;
108 }
109
110 void pt_bcache_free(struct pt_block_cache *bcache)
111 {
112         free(bcache);
113 }
114
115 /* A test fixture providing a temporary file and an initially NULL section. */
116 struct section_fixture {
117         /* Threading support. */
118         struct ptunit_thrd_fixture thrd;
119
120         /* A temporary file name. */
121         char *name;
122
123         /* That file opened for writing. */
124         FILE *file;
125
126         /* The section. */
127         struct pt_section *section;
128
129         /* The test fixture initialization and finalization functions. */
130         struct ptunit_result (*init)(struct section_fixture *);
131         struct ptunit_result (*fini)(struct section_fixture *);
132 };
133
134 enum {
135 #if defined(FEATURE_THREADS)
136
137         num_threads     = 4,
138
139 #endif /* defined(FEATURE_THREADS) */
140
141         num_work        = 0x4000
142 };
143
144 static struct ptunit_result sfix_write_aux(struct section_fixture *sfix,
145                                            const uint8_t *buffer, size_t size)
146 {
147         size_t written;
148
149         written = fwrite(buffer, 1, size, sfix->file);
150         ptu_uint_eq(written, size);
151
152         fflush(sfix->file);
153
154         return ptu_passed();
155 }
156
157 #define sfix_write(sfix, buffer)                                \
158         ptu_check(sfix_write_aux, sfix, buffer, sizeof(buffer))
159
160 static struct ptunit_result create(struct section_fixture *sfix)
161 {
162         const char *name;
163         uint8_t bytes[] = { 0xcc, 0xcc, 0xcc, 0xcc, 0xcc };
164         uint64_t offset, size;
165
166         sfix_write(sfix, bytes);
167
168         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
169         ptu_ptr(sfix->section);
170
171         name = pt_section_filename(sfix->section);
172         ptu_str_eq(name, sfix->name);
173
174         offset = pt_section_offset(sfix->section);
175         ptu_uint_eq(offset, 0x1ull);
176
177         size = pt_section_size(sfix->section);
178         ptu_uint_eq(size, 0x3ull);
179
180         return ptu_passed();
181 }
182
183 static struct ptunit_result create_bad_offset(struct section_fixture *sfix)
184 {
185         sfix->section = pt_mk_section(sfix->name, 0x10ull, 0x0ull);
186         ptu_null(sfix->section);
187
188         return ptu_passed();
189 }
190
191 static struct ptunit_result create_truncated(struct section_fixture *sfix)
192 {
193         const char *name;
194         uint8_t bytes[] = { 0xcc, 0xcc, 0xcc, 0xcc, 0xcc };
195         uint64_t offset, size;
196
197         sfix_write(sfix, bytes);
198
199         sfix->section = pt_mk_section(sfix->name, 0x1ull, UINT64_MAX);
200         ptu_ptr(sfix->section);
201
202         name = pt_section_filename(sfix->section);
203         ptu_str_eq(name, sfix->name);
204
205         offset = pt_section_offset(sfix->section);
206         ptu_uint_eq(offset, 0x1ull);
207
208         size = pt_section_size(sfix->section);
209         ptu_uint_eq(size, sizeof(bytes) - 1);
210
211         return ptu_passed();
212 }
213
214 static struct ptunit_result create_empty(struct section_fixture *sfix)
215 {
216         sfix->section = pt_mk_section(sfix->name, 0x0ull, 0x10ull);
217         ptu_null(sfix->section);
218
219         return ptu_passed();
220 }
221
222 static struct ptunit_result filename_null(void)
223 {
224         const char *name;
225
226         name = pt_section_filename(NULL);
227         ptu_null(name);
228
229         return ptu_passed();
230 }
231
232 static struct ptunit_result size_null(void)
233 {
234         uint64_t size;
235
236         size = pt_section_size(NULL);
237         ptu_uint_eq(size, 0ull);
238
239         return ptu_passed();
240 }
241
242 static struct ptunit_result memsize_null(struct section_fixture *sfix)
243 {
244         uint64_t size;
245         int errcode;
246
247         errcode = pt_section_memsize(NULL, &size);
248         ptu_int_eq(errcode, -pte_internal);
249
250         errcode = pt_section_memsize(sfix->section, NULL);
251         ptu_int_eq(errcode, -pte_internal);
252
253         errcode = pt_section_memsize(NULL, NULL);
254         ptu_int_eq(errcode, -pte_internal);
255
256         return ptu_passed();
257 }
258
259 static struct ptunit_result offset_null(void)
260 {
261         uint64_t offset;
262
263         offset = pt_section_offset(NULL);
264         ptu_uint_eq(offset, 0ull);
265
266         return ptu_passed();
267 }
268
269 static struct ptunit_result get_null(void)
270 {
271         int errcode;
272
273         errcode = pt_section_get(NULL);
274         ptu_int_eq(errcode, -pte_internal);
275
276         return ptu_passed();
277 }
278
279 static struct ptunit_result put_null(void)
280 {
281         int errcode;
282
283         errcode = pt_section_put(NULL);
284         ptu_int_eq(errcode, -pte_internal);
285
286         return ptu_passed();
287 }
288
289 static struct ptunit_result attach_null(void)
290 {
291         struct pt_image_section_cache iscache;
292         struct pt_section section;
293         int errcode;
294
295         errcode = pt_section_attach(NULL, &iscache);
296         ptu_int_eq(errcode, -pte_internal);
297
298         errcode = pt_section_attach(&section, NULL);
299         ptu_int_eq(errcode, -pte_internal);
300
301         errcode = pt_section_attach(NULL, NULL);
302         ptu_int_eq(errcode, -pte_internal);
303
304         return ptu_passed();
305 }
306
307 static struct ptunit_result detach_null(void)
308 {
309         struct pt_image_section_cache iscache;
310         struct pt_section section;
311         int errcode;
312
313         errcode = pt_section_detach(NULL, &iscache);
314         ptu_int_eq(errcode, -pte_internal);
315
316         errcode = pt_section_detach(&section, NULL);
317         ptu_int_eq(errcode, -pte_internal);
318
319         errcode = pt_section_detach(NULL, NULL);
320         ptu_int_eq(errcode, -pte_internal);
321
322         return ptu_passed();
323 }
324
325 static struct ptunit_result map_null(void)
326 {
327         int errcode;
328
329         errcode = pt_section_map(NULL);
330         ptu_int_eq(errcode, -pte_internal);
331
332         return ptu_passed();
333 }
334
335 static struct ptunit_result unmap_null(void)
336 {
337         int errcode;
338
339         errcode = pt_section_unmap(NULL);
340         ptu_int_eq(errcode, -pte_internal);
341
342         return ptu_passed();
343 }
344
345 static struct ptunit_result cache_null(void)
346 {
347         struct pt_block_cache *bcache;
348
349         bcache = pt_section_bcache(NULL);
350         ptu_null(bcache);
351
352         return ptu_passed();
353 }
354
355 static struct ptunit_result get_overflow(struct section_fixture *sfix)
356 {
357         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
358         int errcode;
359
360         sfix_write(sfix, bytes);
361
362         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
363         ptu_ptr(sfix->section);
364
365         sfix->section->ucount = UINT16_MAX;
366
367         errcode = pt_section_get(sfix->section);
368         ptu_int_eq(errcode, -pte_overflow);
369
370         sfix->section->ucount = 1;
371
372         return ptu_passed();
373 }
374
375 static struct ptunit_result attach_overflow(struct section_fixture *sfix)
376 {
377         struct pt_image_section_cache iscache;
378         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
379         int errcode;
380
381         sfix_write(sfix, bytes);
382
383         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
384         ptu_ptr(sfix->section);
385
386         sfix->section->acount = UINT16_MAX;
387
388         errcode = pt_section_attach(sfix->section, &iscache);
389         ptu_int_eq(errcode, -pte_overflow);
390
391         sfix->section->acount = 0;
392
393         return ptu_passed();
394 }
395
396 static struct ptunit_result attach_bad_ucount(struct section_fixture *sfix)
397 {
398         struct pt_image_section_cache iscache;
399         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
400         int errcode;
401
402         sfix_write(sfix, bytes);
403
404         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
405         ptu_ptr(sfix->section);
406
407         sfix->section->acount = 2;
408
409         errcode = pt_section_attach(sfix->section, &iscache);
410         ptu_int_eq(errcode, -pte_internal);
411
412         sfix->section->acount = 0;
413
414         return ptu_passed();
415 }
416
417 static struct ptunit_result map_change(struct section_fixture *sfix)
418 {
419         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
420         int errcode;
421
422         sfix_write(sfix, bytes);
423
424         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
425         ptu_ptr(sfix->section);
426
427         sfix_write(sfix, bytes);
428
429         errcode = pt_section_map(sfix->section);
430         ptu_int_eq(errcode, -pte_bad_image);
431
432         return ptu_passed();
433 }
434
435 static struct ptunit_result map_put(struct section_fixture *sfix)
436 {
437         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
438         int errcode;
439
440         sfix_write(sfix, bytes);
441
442         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
443         ptu_ptr(sfix->section);
444
445         errcode = pt_section_map(sfix->section);
446         ptu_int_eq(errcode, 0);
447
448         errcode = pt_section_put(sfix->section);
449         ptu_int_eq(errcode, -pte_internal);
450
451         errcode = pt_section_unmap(sfix->section);
452         ptu_int_eq(errcode, 0);
453
454         return ptu_passed();
455 }
456
457 static struct ptunit_result unmap_nomap(struct section_fixture *sfix)
458 {
459         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
460         int errcode;
461
462         sfix_write(sfix, bytes);
463
464         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
465         ptu_ptr(sfix->section);
466
467         errcode = pt_section_unmap(sfix->section);
468         ptu_int_eq(errcode, -pte_nomap);
469
470         return ptu_passed();
471 }
472
473 static struct ptunit_result map_overflow(struct section_fixture *sfix)
474 {
475         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
476         int errcode;
477
478         sfix_write(sfix, bytes);
479
480         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
481         ptu_ptr(sfix->section);
482
483         sfix->section->mcount = UINT16_MAX;
484
485         errcode = pt_section_map(sfix->section);
486         ptu_int_eq(errcode, -pte_overflow);
487
488         sfix->section->mcount = 0;
489
490         return ptu_passed();
491 }
492
493 static struct ptunit_result get_put(struct section_fixture *sfix)
494 {
495         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
496         int errcode;
497
498         sfix_write(sfix, bytes);
499
500         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
501         ptu_ptr(sfix->section);
502
503         errcode = pt_section_get(sfix->section);
504         ptu_int_eq(errcode, 0);
505
506         errcode = pt_section_get(sfix->section);
507         ptu_int_eq(errcode, 0);
508
509         errcode = pt_section_put(sfix->section);
510         ptu_int_eq(errcode, 0);
511
512         errcode = pt_section_put(sfix->section);
513         ptu_int_eq(errcode, 0);
514
515         return ptu_passed();
516 }
517
518 static struct ptunit_result attach_detach(struct section_fixture *sfix)
519 {
520         struct pt_image_section_cache iscache;
521         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
522         int errcode;
523
524         sfix_write(sfix, bytes);
525
526         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
527         ptu_ptr(sfix->section);
528
529         sfix->section->ucount += 2;
530
531         errcode = pt_section_attach(sfix->section, &iscache);
532         ptu_int_eq(errcode, 0);
533
534         errcode = pt_section_attach(sfix->section, &iscache);
535         ptu_int_eq(errcode, 0);
536
537         errcode = pt_section_detach(sfix->section, &iscache);
538         ptu_int_eq(errcode, 0);
539
540         errcode = pt_section_detach(sfix->section, &iscache);
541         ptu_int_eq(errcode, 0);
542
543         sfix->section->ucount -= 2;
544
545         return ptu_passed();
546 }
547
548 static struct ptunit_result attach_bad_iscache(struct section_fixture *sfix)
549 {
550         struct pt_image_section_cache iscache, bad;
551         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
552         int errcode;
553
554         sfix_write(sfix, bytes);
555
556         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
557         ptu_ptr(sfix->section);
558
559         sfix->section->ucount += 2;
560
561         errcode = pt_section_attach(sfix->section, &iscache);
562         ptu_int_eq(errcode, 0);
563
564         errcode = pt_section_attach(sfix->section, &bad);
565         ptu_int_eq(errcode, -pte_internal);
566
567         errcode = pt_section_detach(sfix->section, &iscache);
568         ptu_int_eq(errcode, 0);
569
570         sfix->section->ucount -= 2;
571
572         return ptu_passed();
573 }
574
575 static struct ptunit_result detach_bad_iscache(struct section_fixture *sfix)
576 {
577         struct pt_image_section_cache iscache, bad;
578         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
579         int errcode;
580
581         sfix_write(sfix, bytes);
582
583         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
584         ptu_ptr(sfix->section);
585
586         errcode = pt_section_attach(sfix->section, &iscache);
587         ptu_int_eq(errcode, 0);
588
589         errcode = pt_section_detach(sfix->section, &bad);
590         ptu_int_eq(errcode, -pte_internal);
591
592         errcode = pt_section_detach(sfix->section, &iscache);
593         ptu_int_eq(errcode, 0);
594
595         return ptu_passed();
596 }
597
598 static struct ptunit_result map_unmap(struct section_fixture *sfix)
599 {
600         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
601         int errcode;
602
603         sfix_write(sfix, bytes);
604
605         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
606         ptu_ptr(sfix->section);
607
608         errcode = pt_section_map(sfix->section);
609         ptu_int_eq(errcode, 0);
610
611         errcode = pt_section_map(sfix->section);
612         ptu_int_eq(errcode, 0);
613
614         errcode = pt_section_unmap(sfix->section);
615         ptu_int_eq(errcode, 0);
616
617         errcode = pt_section_unmap(sfix->section);
618         ptu_int_eq(errcode, 0);
619
620         return ptu_passed();
621 }
622
623 static struct ptunit_result attach_map(struct section_fixture *sfix)
624 {
625         struct pt_image_section_cache iscache;
626         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
627         int errcode;
628
629         iscache.map = 0;
630
631         sfix_write(sfix, bytes);
632
633         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
634         ptu_ptr(sfix->section);
635
636         errcode = pt_section_attach(sfix->section, &iscache);
637         ptu_int_eq(errcode, 0);
638
639         errcode = pt_section_map(sfix->section);
640         ptu_int_eq(errcode, 0);
641
642         errcode = pt_section_map(sfix->section);
643         ptu_int_eq(errcode, 0);
644
645         ptu_uint_eq(sfix->section->mcount, 2);
646
647         errcode = pt_section_unmap(sfix->section);
648         ptu_int_eq(errcode, 0);
649
650         errcode = pt_section_unmap(sfix->section);
651         ptu_int_eq(errcode, 0);
652
653         errcode = pt_section_detach(sfix->section, &iscache);
654         ptu_int_eq(errcode, 0);
655
656         return ptu_passed();
657 }
658
659 static struct ptunit_result attach_bad_map(struct section_fixture *sfix)
660 {
661         struct pt_image_section_cache iscache;
662         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
663         int errcode;
664
665         iscache.map = -pte_eos;
666
667         sfix_write(sfix, bytes);
668
669         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
670         ptu_ptr(sfix->section);
671
672         errcode = pt_section_attach(sfix->section, &iscache);
673         ptu_int_eq(errcode, 0);
674
675         errcode = pt_section_map(sfix->section);
676         ptu_int_eq(errcode, -pte_eos);
677
678         errcode = pt_section_detach(sfix->section, &iscache);
679         ptu_int_eq(errcode, 0);
680
681         return ptu_passed();
682 }
683
684 static struct ptunit_result attach_map_overflow(struct section_fixture *sfix)
685 {
686         struct pt_image_section_cache iscache;
687         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
688         int errcode;
689
690         iscache.map = 1;
691
692         sfix_write(sfix, bytes);
693
694         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
695         ptu_ptr(sfix->section);
696
697         errcode = pt_section_attach(sfix->section, &iscache);
698         ptu_int_eq(errcode, 0);
699
700         sfix->section->mcount = UINT16_MAX - 1;
701
702         errcode = pt_section_map(sfix->section);
703         ptu_int_eq(errcode, -pte_overflow);
704
705         errcode = pt_section_detach(sfix->section, &iscache);
706         ptu_int_eq(errcode, 0);
707
708         return ptu_passed();
709 }
710
711 static struct ptunit_result read(struct section_fixture *sfix)
712 {
713         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
714         uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
715         int status;
716
717         sfix_write(sfix, bytes);
718
719         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
720         ptu_ptr(sfix->section);
721
722         status = pt_section_map(sfix->section);
723         ptu_int_eq(status, 0);
724
725         status = pt_section_read(sfix->section, buffer, 2, 0x0ull);
726         ptu_int_eq(status, 2);
727         ptu_uint_eq(buffer[0], bytes[1]);
728         ptu_uint_eq(buffer[1], bytes[2]);
729         ptu_uint_eq(buffer[2], 0xcc);
730
731         status = pt_section_unmap(sfix->section);
732         ptu_int_eq(status, 0);
733
734         return ptu_passed();
735 }
736
737 static struct ptunit_result read_null(struct section_fixture *sfix)
738 {
739         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
740         uint8_t buffer[] = { 0xcc };
741         int status;
742
743         sfix_write(sfix, bytes);
744
745         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
746         ptu_ptr(sfix->section);
747
748         status = pt_section_map(sfix->section);
749         ptu_int_eq(status, 0);
750
751         status = pt_section_read(sfix->section, NULL, 1, 0x0ull);
752         ptu_int_eq(status, -pte_internal);
753         ptu_uint_eq(buffer[0], 0xcc);
754
755         status = pt_section_read(NULL, buffer, 1, 0x0ull);
756         ptu_int_eq(status, -pte_internal);
757         ptu_uint_eq(buffer[0], 0xcc);
758
759         status = pt_section_unmap(sfix->section);
760         ptu_int_eq(status, 0);
761
762         return ptu_passed();
763 }
764
765 static struct ptunit_result read_offset(struct section_fixture *sfix)
766 {
767         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
768         uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
769         int status;
770
771         sfix_write(sfix, bytes);
772
773         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
774         ptu_ptr(sfix->section);
775
776         status = pt_section_map(sfix->section);
777         ptu_int_eq(status, 0);
778
779         status = pt_section_read(sfix->section, buffer, 2, 0x1ull);
780         ptu_int_eq(status, 2);
781         ptu_uint_eq(buffer[0], bytes[2]);
782         ptu_uint_eq(buffer[1], bytes[3]);
783         ptu_uint_eq(buffer[2], 0xcc);
784
785         status = pt_section_unmap(sfix->section);
786         ptu_int_eq(status, 0);
787
788         return ptu_passed();
789 }
790
791 static struct ptunit_result read_truncated(struct section_fixture *sfix)
792 {
793         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }, buffer[] = { 0xcc, 0xcc };
794         int status;
795
796         sfix_write(sfix, bytes);
797
798         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
799         ptu_ptr(sfix->section);
800
801         status = pt_section_map(sfix->section);
802         ptu_int_eq(status, 0);
803
804         status = pt_section_read(sfix->section, buffer, 2, 0x2ull);
805         ptu_int_eq(status, 1);
806         ptu_uint_eq(buffer[0], bytes[3]);
807         ptu_uint_eq(buffer[1], 0xcc);
808
809         status = pt_section_unmap(sfix->section);
810         ptu_int_eq(status, 0);
811
812         return ptu_passed();
813 }
814
815 static struct ptunit_result read_from_truncated(struct section_fixture *sfix)
816 {
817         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }, buffer[] = { 0xcc, 0xcc };
818         int status;
819
820         sfix_write(sfix, bytes);
821
822         sfix->section = pt_mk_section(sfix->name, 0x2ull, 0x10ull);
823         ptu_ptr(sfix->section);
824
825         status = pt_section_map(sfix->section);
826         ptu_int_eq(status, 0);
827
828         status = pt_section_read(sfix->section, buffer, 2, 0x1ull);
829         ptu_int_eq(status, 1);
830         ptu_uint_eq(buffer[0], bytes[3]);
831         ptu_uint_eq(buffer[1], 0xcc);
832
833         status = pt_section_unmap(sfix->section);
834         ptu_int_eq(status, 0);
835
836         return ptu_passed();
837 }
838
839 static struct ptunit_result read_nomem(struct section_fixture *sfix)
840 {
841         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }, buffer[] = { 0xcc };
842         int status;
843
844         sfix_write(sfix, bytes);
845
846         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
847         ptu_ptr(sfix->section);
848
849         status = pt_section_map(sfix->section);
850         ptu_int_eq(status, 0);
851
852         status = pt_section_read(sfix->section, buffer, 1, 0x3ull);
853         ptu_int_eq(status, -pte_nomap);
854         ptu_uint_eq(buffer[0], 0xcc);
855
856         status = pt_section_unmap(sfix->section);
857         ptu_int_eq(status, 0);
858
859         return ptu_passed();
860 }
861
862 static struct ptunit_result read_overflow(struct section_fixture *sfix)
863 {
864         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }, buffer[] = { 0xcc };
865         int status;
866
867         sfix_write(sfix, bytes);
868
869         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
870         ptu_ptr(sfix->section);
871
872         status = pt_section_map(sfix->section);
873         ptu_int_eq(status, 0);
874
875         status = pt_section_read(sfix->section, buffer, 1,
876                                  0xffffffffffff0000ull);
877         ptu_int_eq(status, -pte_nomap);
878         ptu_uint_eq(buffer[0], 0xcc);
879
880         status = pt_section_unmap(sfix->section);
881         ptu_int_eq(status, 0);
882
883         return ptu_passed();
884 }
885
886 static struct ptunit_result read_overflow_32bit(struct section_fixture *sfix)
887 {
888         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }, buffer[] = { 0xcc };
889         int status;
890
891         sfix_write(sfix, bytes);
892
893         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
894         ptu_ptr(sfix->section);
895
896         status = pt_section_map(sfix->section);
897         ptu_int_eq(status, 0);
898
899         status = pt_section_read(sfix->section, buffer, 1,
900                                  0xff00000000ull);
901         ptu_int_eq(status, -pte_nomap);
902         ptu_uint_eq(buffer[0], 0xcc);
903
904         status = pt_section_unmap(sfix->section);
905         ptu_int_eq(status, 0);
906
907         return ptu_passed();
908 }
909
910 static struct ptunit_result read_nomap(struct section_fixture *sfix)
911 {
912         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }, buffer[] = { 0xcc };
913         int status;
914
915         sfix_write(sfix, bytes);
916
917         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
918         ptu_ptr(sfix->section);
919
920         status = pt_section_read(sfix->section, buffer, 1, 0x0ull);
921         ptu_int_eq(status, -pte_nomap);
922         ptu_uint_eq(buffer[0], 0xcc);
923
924         return ptu_passed();
925 }
926
927 static struct ptunit_result read_unmap_map(struct section_fixture *sfix)
928 {
929         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
930         uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
931         int status;
932
933         sfix_write(sfix, bytes);
934
935         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
936         ptu_ptr(sfix->section);
937
938         status = pt_section_map(sfix->section);
939         ptu_int_eq(status, 0);
940
941         status = pt_section_read(sfix->section, buffer, 2, 0x0ull);
942         ptu_int_eq(status, 2);
943         ptu_uint_eq(buffer[0], bytes[1]);
944         ptu_uint_eq(buffer[1], bytes[2]);
945         ptu_uint_eq(buffer[2], 0xcc);
946
947         memset(buffer, 0xcc, sizeof(buffer));
948
949         status = pt_section_unmap(sfix->section);
950         ptu_int_eq(status, 0);
951
952         status = pt_section_read(sfix->section, buffer, 2, 0x0ull);
953         ptu_int_eq(status, -pte_nomap);
954         ptu_uint_eq(buffer[0], 0xcc);
955         ptu_uint_eq(buffer[1], 0xcc);
956         ptu_uint_eq(buffer[2], 0xcc);
957
958         status = pt_section_map(sfix->section);
959         ptu_int_eq(status, 0);
960
961         status = pt_section_read(sfix->section, buffer, 2, 0x0ull);
962         ptu_int_eq(status, 2);
963         ptu_uint_eq(buffer[0], bytes[1]);
964         ptu_uint_eq(buffer[1], bytes[2]);
965         ptu_uint_eq(buffer[2], 0xcc);
966
967         status = pt_section_unmap(sfix->section);
968         ptu_int_eq(status, 0);
969
970         return ptu_passed();
971 }
972
973 static int worker_read(void *arg)
974 {
975         struct section_fixture *sfix;
976         int it, errcode;
977
978         sfix = arg;
979         if (!sfix)
980                 return -pte_internal;
981
982         for (it = 0; it < num_work; ++it) {
983                 uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
984                 int read;
985
986                 errcode = pt_section_get(sfix->section);
987                 if (errcode < 0)
988                         return errcode;
989
990                 errcode = pt_section_map(sfix->section);
991                 if (errcode < 0)
992                         goto out_put;
993
994                 read = pt_section_read(sfix->section, buffer, 2, 0x0ull);
995                 if (read < 0)
996                         goto out_unmap;
997
998                 errcode = -pte_invalid;
999                 if ((read != 2) || (buffer[0] != 0x2) || (buffer[1] != 0x4))
1000                         goto out_unmap;
1001
1002                 errcode = pt_section_unmap(sfix->section);
1003                 if (errcode < 0)
1004                         goto out_put;
1005
1006                 errcode = pt_section_put(sfix->section);
1007                 if (errcode < 0)
1008                         return errcode;
1009         }
1010
1011         return 0;
1012
1013 out_unmap:
1014         (void) pt_section_unmap(sfix->section);
1015
1016 out_put:
1017         (void) pt_section_put(sfix->section);
1018         return errcode;
1019 }
1020
1021 static int worker_bcache(void *arg)
1022 {
1023         struct section_fixture *sfix;
1024         int it, errcode;
1025
1026         sfix = arg;
1027         if (!sfix)
1028                 return -pte_internal;
1029
1030         errcode = pt_section_get(sfix->section);
1031         if (errcode < 0)
1032                 return errcode;
1033
1034         for (it = 0; it < num_work; ++it) {
1035                 struct pt_block_cache *bcache;
1036
1037                 errcode = pt_section_map(sfix->section);
1038                 if (errcode < 0)
1039                         goto out_put;
1040
1041                 errcode = pt_section_request_bcache(sfix->section);
1042                 if (errcode < 0)
1043                         goto out_unmap;
1044
1045                 bcache = pt_section_bcache(sfix->section);
1046                 if (!bcache) {
1047                         errcode = -pte_nomem;
1048                         goto out_unmap;
1049                 }
1050
1051                 errcode = pt_section_unmap(sfix->section);
1052                 if (errcode < 0)
1053                         goto out_put;
1054         }
1055
1056         return pt_section_put(sfix->section);
1057
1058 out_unmap:
1059         (void) pt_section_unmap(sfix->section);
1060
1061 out_put:
1062         (void) pt_section_put(sfix->section);
1063         return errcode;
1064 }
1065
1066 static struct ptunit_result stress(struct section_fixture *sfix,
1067                                    int (*worker)(void *))
1068 {
1069         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
1070         int errcode;
1071
1072         sfix_write(sfix, bytes);
1073
1074         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
1075         ptu_ptr(sfix->section);
1076
1077 #if defined(FEATURE_THREADS)
1078         {
1079                 int thrd;
1080
1081                 for (thrd = 0; thrd < num_threads; ++thrd)
1082                         ptu_test(ptunit_thrd_create, &sfix->thrd, worker, sfix);
1083         }
1084 #endif /* defined(FEATURE_THREADS) */
1085
1086         errcode = worker(sfix);
1087         ptu_int_eq(errcode, 0);
1088
1089         return ptu_passed();
1090 }
1091
1092 static struct ptunit_result init_no_bcache(struct section_fixture *sfix)
1093 {
1094         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
1095         struct pt_block_cache *bcache;
1096         int errcode;
1097
1098         sfix_write(sfix, bytes);
1099
1100         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
1101         ptu_ptr(sfix->section);
1102
1103         errcode = pt_section_map(sfix->section);
1104         ptu_int_eq(errcode, 0);
1105
1106         bcache = pt_section_bcache(sfix->section);
1107         ptu_null(bcache);
1108
1109         errcode = pt_section_unmap(sfix->section);
1110         ptu_int_eq(errcode, 0);
1111
1112         return ptu_passed();
1113 }
1114
1115 static struct ptunit_result bcache_alloc_free(struct section_fixture *sfix)
1116 {
1117         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
1118         struct pt_block_cache *bcache;
1119         int errcode;
1120
1121         sfix_write(sfix, bytes);
1122
1123         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
1124         ptu_ptr(sfix->section);
1125
1126         errcode = pt_section_map(sfix->section);
1127         ptu_int_eq(errcode, 0);
1128
1129         errcode = pt_section_alloc_bcache(sfix->section);
1130         ptu_int_eq(errcode, 0);
1131
1132         bcache = pt_section_bcache(sfix->section);
1133         ptu_ptr(bcache);
1134         ptu_uint_eq(bcache->nentries, sfix->section->size);
1135
1136         errcode = pt_section_unmap(sfix->section);
1137         ptu_int_eq(errcode, 0);
1138
1139         bcache = pt_section_bcache(sfix->section);
1140         ptu_null(bcache);
1141
1142         return ptu_passed();
1143 }
1144
1145 static struct ptunit_result bcache_alloc_twice(struct section_fixture *sfix)
1146 {
1147         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
1148         int errcode;
1149
1150         sfix_write(sfix, bytes);
1151
1152         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
1153         ptu_ptr(sfix->section);
1154
1155         errcode = pt_section_map(sfix->section);
1156         ptu_int_eq(errcode, 0);
1157
1158         errcode = pt_section_alloc_bcache(sfix->section);
1159         ptu_int_eq(errcode, 0);
1160
1161         errcode = pt_section_alloc_bcache(sfix->section);
1162         ptu_int_eq(errcode, 0);
1163
1164         errcode = pt_section_unmap(sfix->section);
1165         ptu_int_eq(errcode, 0);
1166
1167         return ptu_passed();
1168 }
1169
1170 static struct ptunit_result bcache_alloc_nomap(struct section_fixture *sfix)
1171 {
1172         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
1173         int errcode;
1174
1175         sfix_write(sfix, bytes);
1176
1177         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
1178         ptu_ptr(sfix->section);
1179
1180         errcode = pt_section_alloc_bcache(sfix->section);
1181         ptu_int_eq(errcode, -pte_internal);
1182
1183         return ptu_passed();
1184 }
1185
1186 static struct ptunit_result memsize_nomap(struct section_fixture *sfix)
1187 {
1188         uint64_t memsize;
1189         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
1190         int errcode;
1191
1192         sfix_write(sfix, bytes);
1193
1194         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
1195         ptu_ptr(sfix->section);
1196
1197         errcode = pt_section_memsize(sfix->section, &memsize);
1198         ptu_int_eq(errcode, 0);
1199         ptu_uint_eq(memsize, 0ull);
1200
1201         return ptu_passed();
1202 }
1203
1204 static struct ptunit_result memsize_unmap(struct section_fixture *sfix)
1205 {
1206         uint64_t memsize;
1207         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
1208         int errcode;
1209
1210         sfix_write(sfix, bytes);
1211
1212         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
1213         ptu_ptr(sfix->section);
1214
1215         errcode = pt_section_map(sfix->section);
1216         ptu_int_eq(errcode, 0);
1217
1218         errcode = pt_section_unmap(sfix->section);
1219         ptu_int_eq(errcode, 0);
1220
1221         errcode = pt_section_memsize(sfix->section, &memsize);
1222         ptu_int_eq(errcode, 0);
1223         ptu_uint_eq(memsize, 0ull);
1224
1225         return ptu_passed();
1226 }
1227
1228 static struct ptunit_result memsize_map_nobcache(struct section_fixture *sfix)
1229 {
1230         uint64_t memsize;
1231         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
1232         int errcode;
1233
1234         sfix_write(sfix, bytes);
1235
1236         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
1237         ptu_ptr(sfix->section);
1238
1239         errcode = pt_section_map(sfix->section);
1240         ptu_int_eq(errcode, 0);
1241
1242         memsize = 0xfefefefefefefefeull;
1243
1244         errcode = pt_section_memsize(sfix->section, &memsize);
1245         ptu_int_eq(errcode, 0);
1246         ptu_uint_ge(memsize, 0ull);
1247         ptu_uint_le(memsize, 0x2000ull);
1248
1249         errcode = pt_section_unmap(sfix->section);
1250         ptu_int_eq(errcode, 0);
1251
1252         return ptu_passed();
1253 }
1254
1255 static struct ptunit_result memsize_map_bcache(struct section_fixture *sfix)
1256 {
1257         uint64_t memsize;
1258         uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
1259         int errcode;
1260
1261         sfix_write(sfix, bytes);
1262
1263         sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
1264         ptu_ptr(sfix->section);
1265
1266         errcode = pt_section_map(sfix->section);
1267         ptu_int_eq(errcode, 0);
1268
1269         errcode = pt_section_alloc_bcache(sfix->section);
1270         ptu_int_eq(errcode, 0);
1271
1272         errcode = pt_section_memsize(sfix->section, &memsize);
1273         ptu_int_eq(errcode, 0);
1274         ptu_uint_ge(memsize,
1275                     sfix->section->size * sizeof(struct pt_bcache_entry));
1276
1277         errcode = pt_section_unmap(sfix->section);
1278         ptu_int_eq(errcode, 0);
1279
1280         return ptu_passed();
1281 }
1282
1283 static struct ptunit_result sfix_init(struct section_fixture *sfix)
1284 {
1285         int errcode;
1286
1287         sfix->section = NULL;
1288         sfix->file = NULL;
1289         sfix->name = NULL;
1290
1291         errcode = ptunit_mkfile(&sfix->file, &sfix->name, "wb");
1292         ptu_int_eq(errcode, 0);
1293
1294         ptu_test(ptunit_thrd_init, &sfix->thrd);
1295
1296         return ptu_passed();
1297 }
1298
1299 static struct ptunit_result sfix_fini(struct section_fixture *sfix)
1300 {
1301         int thrd;
1302
1303         ptu_test(ptunit_thrd_fini, &sfix->thrd);
1304
1305         for (thrd = 0; thrd < sfix->thrd.nthreads; ++thrd)
1306                 ptu_int_eq(sfix->thrd.result[thrd], 0);
1307
1308         if (sfix->section) {
1309                 pt_section_put(sfix->section);
1310                 sfix->section = NULL;
1311         }
1312
1313         if (sfix->file) {
1314                 fclose(sfix->file);
1315                 sfix->file = NULL;
1316
1317                 if (sfix->name)
1318                         remove(sfix->name);
1319         }
1320
1321         if (sfix->name) {
1322                 free(sfix->name);
1323                 sfix->name = NULL;
1324         }
1325
1326         return ptu_passed();
1327 }
1328
1329 int main(int argc, char **argv)
1330 {
1331         struct section_fixture sfix;
1332         struct ptunit_suite suite;
1333
1334         sfix.init = sfix_init;
1335         sfix.fini = sfix_fini;
1336
1337         suite = ptunit_mk_suite(argc, argv);
1338
1339         ptu_run_f(suite, create, sfix);
1340         ptu_run_f(suite, create_bad_offset, sfix);
1341         ptu_run_f(suite, create_truncated, sfix);
1342         ptu_run_f(suite, create_empty, sfix);
1343
1344         ptu_run(suite, filename_null);
1345         ptu_run(suite, offset_null);
1346         ptu_run(suite, size_null);
1347         ptu_run(suite, get_null);
1348         ptu_run(suite, put_null);
1349         ptu_run(suite, attach_null);
1350         ptu_run(suite, detach_null);
1351         ptu_run(suite, map_null);
1352         ptu_run(suite, unmap_null);
1353         ptu_run(suite, cache_null);
1354
1355         ptu_run_f(suite, get_overflow, sfix);
1356         ptu_run_f(suite, attach_overflow, sfix);
1357         ptu_run_f(suite, attach_bad_ucount, sfix);
1358         ptu_run_f(suite, map_change, sfix);
1359         ptu_run_f(suite, map_put, sfix);
1360         ptu_run_f(suite, unmap_nomap, sfix);
1361         ptu_run_f(suite, map_overflow, sfix);
1362         ptu_run_f(suite, get_put, sfix);
1363         ptu_run_f(suite, attach_detach, sfix);
1364         ptu_run_f(suite, attach_bad_iscache, sfix);
1365         ptu_run_f(suite, detach_bad_iscache, sfix);
1366         ptu_run_f(suite, map_unmap, sfix);
1367         ptu_run_f(suite, attach_map, sfix);
1368         ptu_run_f(suite, attach_bad_map, sfix);
1369         ptu_run_f(suite, attach_map_overflow, sfix);
1370         ptu_run_f(suite, read, sfix);
1371         ptu_run_f(suite, read_null, sfix);
1372         ptu_run_f(suite, read_offset, sfix);
1373         ptu_run_f(suite, read_truncated, sfix);
1374         ptu_run_f(suite, read_from_truncated, sfix);
1375         ptu_run_f(suite, read_nomem, sfix);
1376         ptu_run_f(suite, read_overflow, sfix);
1377         ptu_run_f(suite, read_overflow_32bit, sfix);
1378         ptu_run_f(suite, read_nomap, sfix);
1379         ptu_run_f(suite, read_unmap_map, sfix);
1380
1381         ptu_run_f(suite, init_no_bcache, sfix);
1382         ptu_run_f(suite, bcache_alloc_free, sfix);
1383         ptu_run_f(suite, bcache_alloc_twice, sfix);
1384         ptu_run_f(suite, bcache_alloc_nomap, sfix);
1385
1386         ptu_run_f(suite, memsize_null, sfix);
1387         ptu_run_f(suite, memsize_nomap, sfix);
1388         ptu_run_f(suite, memsize_unmap, sfix);
1389         ptu_run_f(suite, memsize_map_nobcache, sfix);
1390         ptu_run_f(suite, memsize_map_bcache, sfix);
1391
1392         ptu_run_fp(suite, stress, sfix, worker_bcache);
1393         ptu_run_fp(suite, stress, sfix, worker_read);
1394
1395         return ptunit_report(&suite);
1396 }