├── .gitignore ├── ASSIGNMENT ├── Build ├── COPYING ├── GNUmakefile ├── LICENSE.txt ├── Makeconfig ├── Makefunctions ├── Makeoptions ├── Makerules ├── NEWS ├── README ├── README.build-system ├── README.md ├── SECURITY.md ├── TODO.org ├── UNTESTED ├── doc └── ctf-format ├── include ├── Build ├── GNUmakefile └── sys │ ├── ctf-api.h │ ├── ctf.h │ └── ctf_types.h ├── libctf ├── Build ├── GNUmakefile ├── bsearch_r.c ├── ctf-archive.c ├── ctf-create.c ├── ctf-decl.c ├── ctf-decls.h ├── ctf-dump.c ├── ctf-endian.h ├── ctf-error.c ├── ctf-hash.c ├── ctf-impl.h ├── ctf-labels.c ├── ctf-link.c ├── ctf-lookup.c ├── ctf-open-bfd.c ├── ctf-open.c ├── ctf-string.c ├── ctf-subr.c ├── ctf-types.c ├── ctf-util.c ├── libdtrace-ctf.ver └── swap.h ├── libdtrace-ctf.spec ├── maint ├── .last-sync.binutils-gdb ├── Makefile.maint ├── comment-change.awk └── header └── tools ├── Build ├── car.c └── ctf_dump.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.[oa] 2 | build-*/ 3 | *~ 4 | -------------------------------------------------------------------------------- /ASSIGNMENT: -------------------------------------------------------------------------------- 1 | Contributions to this library require a copyright assignment to Oracle, Inc, 2 | since it is not only used in the Linux kernel build process but also in the 3 | DTrace for Linux userspace, which is licensed under the UPLv1. 4 | -------------------------------------------------------------------------------- /Build: -------------------------------------------------------------------------------- 1 | # Projects using the DTrace build system can incorporate this project 2 | # directly by just including this project above their project's root 3 | # directory. 4 | # 5 | # So we need to include a fragment in Build to include sub-Builds 6 | # for the sake of such projects. 7 | 8 | ifneq ($(PROJECT),libdtrace-ctf) 9 | include $(wildcard $(sort $(current-dir)/*/Build)) 10 | endif 11 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | 2 | GNU GENERAL PUBLIC LICENSE 3 | Version 2, June 1991 4 | 5 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 6 | 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 7 | Everyone is permitted to copy and distribute verbatim copies 8 | of this license document, but changing it is not allowed. 9 | 10 | Preamble 11 | 12 | The licenses for most software are designed to take away your 13 | freedom to share and change it. By contrast, the GNU General Public 14 | License is intended to guarantee your freedom to share and change free 15 | software--to make sure the software is free for all its users. This 16 | General Public License applies to most of the Free Software 17 | Foundation's software and to any other program whose authors commit to 18 | using it. (Some other Free Software Foundation software is covered by 19 | the GNU Library General Public License instead.) You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | this service if you wish), that you receive source code or can get it 26 | if you want it, that you can change the software or use pieces of it 27 | in new free programs; and that you know you can do these things. 28 | 29 | To protect your rights, we need to make restrictions that forbid 30 | anyone to deny you these rights or to ask you to surrender the rights. 31 | These restrictions translate to certain responsibilities for you if you 32 | distribute copies of the software, or if you modify it. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must give the recipients all the rights that 36 | you have. You must make sure that they, too, receive or can get the 37 | source code. And you must show them these terms so they know their 38 | rights. 39 | 40 | We protect your rights with two steps: (1) copyright the software, and 41 | (2) offer you this license which gives you legal permission to copy, 42 | distribute and/or modify the software. 43 | 44 | Also, for each author's protection and ours, we want to make certain 45 | that everyone understands that there is no warranty for this free 46 | software. If the software is modified by someone else and passed on, we 47 | want its recipients to know that what they have is not the original, so 48 | that any problems introduced by others will not reflect on the original 49 | authors' reputations. 50 | 51 | Finally, any free program is threatened constantly by software 52 | patents. We wish to avoid the danger that redistributors of a free 53 | program will individually obtain patent licenses, in effect making the 54 | program proprietary. To prevent this, we have made it clear that any 55 | patent must be licensed for everyone's free use or not licensed at all. 56 | 57 | The precise terms and conditions for copying, distribution and 58 | modification follow. 59 | 60 | GNU GENERAL PUBLIC LICENSE 61 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 62 | 63 | 0. This License applies to any program or other work which contains 64 | a notice placed by the copyright holder saying it may be distributed 65 | under the terms of this General Public License. The "Program", below, 66 | refers to any such program or work, and a "work based on the Program" 67 | means either the Program or any derivative work under copyright law: 68 | that is to say, a work containing the Program or a portion of it, 69 | either verbatim or with modifications and/or translated into another 70 | language. (Hereinafter, translation is included without limitation in 71 | the term "modification".) Each licensee is addressed as "you". 72 | 73 | Activities other than copying, distribution and modification are not 74 | covered by this License; they are outside its scope. The act of 75 | running the Program is not restricted, and the output from the Program 76 | is covered only if its contents constitute a work based on the 77 | Program (independent of having been made by running the Program). 78 | Whether that is true depends on what the Program does. 79 | 80 | 1. You may copy and distribute verbatim copies of the Program's 81 | source code as you receive it, in any medium, provided that you 82 | conspicuously and appropriately publish on each copy an appropriate 83 | copyright notice and disclaimer of warranty; keep intact all the 84 | notices that refer to this License and to the absence of any warranty; 85 | and give any other recipients of the Program a copy of this License 86 | along with the Program. 87 | 88 | You may charge a fee for the physical act of transferring a copy, and 89 | you may at your option offer warranty protection in exchange for a fee. 90 | 91 | 2. You may modify your copy or copies of the Program or any portion 92 | of it, thus forming a work based on the Program, and copy and 93 | distribute such modifications or work under the terms of Section 1 94 | above, provided that you also meet all of these conditions: 95 | 96 | a) You must cause the modified files to carry prominent notices 97 | stating that you changed the files and the date of any change. 98 | 99 | b) You must cause any work that you distribute or publish, that in 100 | whole or in part contains or is derived from the Program or any 101 | part thereof, to be licensed as a whole at no charge to all third 102 | parties under the terms of this License. 103 | 104 | c) If the modified program normally reads commands interactively 105 | when run, you must cause it, when started running for such 106 | interactive use in the most ordinary way, to print or display an 107 | announcement including an appropriate copyright notice and a 108 | notice that there is no warranty (or else, saying that you provide 109 | a warranty) and that users may redistribute the program under 110 | these conditions, and telling the user how to view a copy of this 111 | License. (Exception: if the Program itself is interactive but 112 | does not normally print such an announcement, your work based on 113 | the Program is not required to print an announcement.) 114 | 115 | These requirements apply to the modified work as a whole. If 116 | identifiable sections of that work are not derived from the Program, 117 | and can be reasonably considered independent and separate works in 118 | themselves, then this License, and its terms, do not apply to those 119 | sections when you distribute them as separate works. But when you 120 | distribute the same sections as part of a whole which is a work based 121 | on the Program, the distribution of the whole must be on the terms of 122 | this License, whose permissions for other licensees extend to the 123 | entire whole, and thus to each and every part regardless of who wrote it. 124 | 125 | Thus, it is not the intent of this section to claim rights or contest 126 | your rights to work written entirely by you; rather, the intent is to 127 | exercise the right to control the distribution of derivative or 128 | collective works based on the Program. 129 | 130 | In addition, mere aggregation of another work not based on the Program 131 | with the Program (or with a work based on the Program) on a volume of 132 | a storage or distribution medium does not bring the other work under 133 | the scope of this License. 134 | 135 | 3. You may copy and distribute the Program (or a work based on it, 136 | under Section 2) in object code or executable form under the terms of 137 | Sections 1 and 2 above provided that you also do one of the following: 138 | 139 | a) Accompany it with the complete corresponding machine-readable 140 | source code, which must be distributed under the terms of Sections 141 | 1 and 2 above on a medium customarily used for software interchange; or, 142 | 143 | b) Accompany it with a written offer, valid for at least three 144 | years, to give any third party, for a charge no more than your 145 | cost of physically performing source distribution, a complete 146 | machine-readable copy of the corresponding source code, to be 147 | distributed under the terms of Sections 1 and 2 above on a medium 148 | customarily used for software interchange; or, 149 | 150 | c) Accompany it with the information you received as to the offer 151 | to distribute corresponding source code. (This alternative is 152 | allowed only for noncommercial distribution and only if you 153 | received the program in object code or executable form with such 154 | an offer, in accord with Subsection b above.) 155 | 156 | The source code for a work means the preferred form of the work for 157 | making modifications to it. For an executable work, complete source 158 | code means all the source code for all modules it contains, plus any 159 | associated interface definition files, plus the scripts used to 160 | control compilation and installation of the executable. However, as a 161 | special exception, the source code distributed need not include 162 | anything that is normally distributed (in either source or binary 163 | form) with the major components (compiler, kernel, and so on) of the 164 | operating system on which the executable runs, unless that component 165 | itself accompanies the executable. 166 | 167 | If distribution of executable or object code is made by offering 168 | access to copy from a designated place, then offering equivalent 169 | access to copy the source code from the same place counts as 170 | distribution of the source code, even though third parties are not 171 | compelled to copy the source along with the object code. 172 | 173 | 4. You may not copy, modify, sublicense, or distribute the Program 174 | except as expressly provided under this License. Any attempt 175 | otherwise to copy, modify, sublicense or distribute the Program is 176 | void, and will automatically terminate your rights under this License. 177 | However, parties who have received copies, or rights, from you under 178 | this License will not have their licenses terminated so long as such 179 | parties remain in full compliance. 180 | 181 | 5. You are not required to accept this License, since you have not 182 | signed it. However, nothing else grants you permission to modify or 183 | distribute the Program or its derivative works. These actions are 184 | prohibited by law if you do not accept this License. Therefore, by 185 | modifying or distributing the Program (or any work based on the 186 | Program), you indicate your acceptance of this License to do so, and 187 | all its terms and conditions for copying, distributing or modifying 188 | the Program or works based on it. 189 | 190 | 6. Each time you redistribute the Program (or any work based on the 191 | Program), the recipient automatically receives a license from the 192 | original licensor to copy, distribute or modify the Program subject to 193 | these terms and conditions. You may not impose any further 194 | restrictions on the recipients' exercise of the rights granted herein. 195 | You are not responsible for enforcing compliance by third parties to 196 | this License. 197 | 198 | 7. If, as a consequence of a court judgment or allegation of patent 199 | infringement or for any other reason (not limited to patent issues), 200 | conditions are imposed on you (whether by court order, agreement or 201 | otherwise) that contradict the conditions of this License, they do not 202 | excuse you from the conditions of this License. If you cannot 203 | distribute so as to satisfy simultaneously your obligations under this 204 | License and any other pertinent obligations, then as a consequence you 205 | may not distribute the Program at all. For example, if a patent 206 | license would not permit royalty-free redistribution of the Program by 207 | all those who receive copies directly or indirectly through you, then 208 | the only way you could satisfy both it and this License would be to 209 | refrain entirely from distribution of the Program. 210 | 211 | If any portion of this section is held invalid or unenforceable under 212 | any particular circumstance, the balance of the section is intended to 213 | apply and the section as a whole is intended to apply in other 214 | circumstances. 215 | 216 | It is not the purpose of this section to induce you to infringe any 217 | patents or other property right claims or to contest validity of any 218 | such claims; this section has the sole purpose of protecting the 219 | integrity of the free software distribution system, which is 220 | implemented by public license practices. Many people have made 221 | generous contributions to the wide range of software distributed 222 | through that system in reliance on consistent application of that 223 | system; it is up to the author/donor to decide if he or she is willing 224 | to distribute software through any other system and a licensee cannot 225 | impose that choice. 226 | 227 | This section is intended to make thoroughly clear what is believed to 228 | be a consequence of the rest of this License. 229 | 230 | 8. If the distribution and/or use of the Program is restricted in 231 | certain countries either by patents or by copyrighted interfaces, the 232 | original copyright holder who places the Program under this License 233 | may add an explicit geographical distribution limitation excluding 234 | those countries, so that distribution is permitted only in or among 235 | countries not thus excluded. In such case, this License incorporates 236 | the limitation as if written in the body of this License. 237 | 238 | 9. The Free Software Foundation may publish revised and/or new versions 239 | of the General Public License from time to time. Such new versions will 240 | be similar in spirit to the present version, but may differ in detail to 241 | address new problems or concerns. 242 | 243 | Each version is given a distinguishing version number. If the Program 244 | specifies a version number of this License which applies to it and "any 245 | later version", you have the option of following the terms and conditions 246 | either of that version or of any later version published by the Free 247 | Software Foundation. If the Program does not specify a version number of 248 | this License, you may choose any version ever published by the Free Software 249 | Foundation. 250 | 251 | 10. If you wish to incorporate parts of the Program into other free 252 | programs whose distribution conditions are different, write to the author 253 | to ask for permission. For software which is copyrighted by the Free 254 | Software Foundation, write to the Free Software Foundation; we sometimes 255 | make exceptions for this. Our decision will be guided by the two goals 256 | of preserving the free status of all derivatives of our free software and 257 | of promoting the sharing and reuse of software generally. 258 | 259 | NO WARRANTY 260 | 261 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 262 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 263 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 264 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 265 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 266 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 267 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 268 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 269 | REPAIR OR CORRECTION. 270 | 271 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 272 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 273 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 274 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 275 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 276 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 277 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 278 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 279 | POSSIBILITY OF SUCH DAMAGES. 280 | 281 | END OF TERMS AND CONDITIONS 282 | 283 | How to Apply These Terms to Your New Programs 284 | 285 | If you develop a new program, and you want it to be of the greatest 286 | possible use to the public, the best way to achieve this is to make it 287 | free software which everyone can redistribute and change under these terms. 288 | 289 | To do so, attach the following notices to the program. It is safest 290 | to attach them to the start of each source file to most effectively 291 | convey the exclusion of warranty; and each file should have at least 292 | the "copyright" line and a pointer to where the full notice is found. 293 | 294 | 295 | Copyright (C) 296 | 297 | This program is free software; you can redistribute it and/or modify 298 | it under the terms of the GNU General Public License as published by 299 | the Free Software Foundation; either version 2 of the License, or 300 | (at your option) any later version. 301 | 302 | This program is distributed in the hope that it will be useful, 303 | but WITHOUT ANY WARRANTY; without even the implied warranty of 304 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 305 | GNU General Public License for more details. 306 | 307 | You should have received a copy of the GNU General Public License 308 | along with this program; if not, write to the Free Software 309 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 310 | 311 | 312 | Also add information on how to contact you by electronic and paper mail. 313 | 314 | If the program is interactive, make it output a short notice like this 315 | when it starts in an interactive mode: 316 | 317 | Gnomovision version 69, Copyright (C) year name of author 318 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 319 | This is free software, and you are welcome to redistribute it 320 | under certain conditions; type `show c' for details. 321 | 322 | The hypothetical commands `show w' and `show c' should show the appropriate 323 | parts of the General Public License. Of course, the commands you use may 324 | be called something other than `show w' and `show c'; they could even be 325 | mouse-clicks or menu items--whatever suits your program. 326 | 327 | You should also get your employer (if you work as a programmer) or your 328 | school, if any, to sign a "copyright disclaimer" for the program, if 329 | necessary. Here is a sample; alter the names: 330 | 331 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 332 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 333 | 334 | , 1 April 1989 335 | Ty Coon, President of Vice 336 | 337 | This General Public License does not permit incorporating your program into 338 | proprietary programs. If your program is a subroutine library, you may 339 | consider it more useful to permit linking proprietary applications with the 340 | library. If this is what you want to do, use the GNU Library General 341 | Public License instead of this License. 342 | -------------------------------------------------------------------------------- /GNUmakefile: -------------------------------------------------------------------------------- 1 | # Top-level makefile for libdtrace-ctf. 2 | # 3 | # Build files in subdirectories are included by this file. 4 | # 5 | # Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. 6 | # 7 | # Licensed under the Universal Permissive License v 1.0 as shown at 8 | # http://oss.oracle.com/licenses/upl. 9 | # 10 | # Licensed under the GNU General Public License (GPL), version 2. See the file 11 | # COPYING in the top level of this tree. 12 | 13 | .DELETE_ON_ERROR: 14 | .SUFFIXES: 15 | 16 | PROJECT := libdtrace-ctf 17 | VERSION := 1.2.0 18 | 19 | # Verify supported hardware. 20 | 21 | $(if $(subst sparc64,,$(subst aarch64,,$(subst x86_64,,$(shell uname -m)))), \ 22 | $(error "Error: DTrace for Linux only supports x86_64, ARM64 and sparc64"),) 23 | $(if $(subst Linux,,$(shell uname -s)), \ 24 | $(error "Error: DTrace only supports Linux"),) 25 | 26 | CFLAGS ?= -O2 -Wall -pedantic -Wno-unknown-pragmas 27 | LDFLAGS ?= 28 | INVARIANT_CFLAGS := -std=gnu11 -D_GNU_SOURCE -DPACKAGE=\"libctf\" $(DTO) 29 | CPPFLAGS += -Iinclude -I$(objdir) 30 | CC = gcc 31 | override CFLAGS += $(INVARIANT_CFLAGS) 32 | PREPROCESS = $(CC) -E -C 33 | 34 | prefix = /usr 35 | objdir := build-$(shell uname -r) 36 | LIBDIR := $(DESTDIR)$(prefix)/lib64 37 | BINDIR := $(DESTDIR)$(prefix)/bin 38 | INCLUDEDIR := $(DESTDIR)$(prefix)/include 39 | SBINDIR := $(DESTDIR)$(prefix)/sbin 40 | DOCDIR := $(DESTDIR)$(prefix)/share/doc/libdtrace-ctf-$(VERSION) 41 | TARGETS = 42 | 43 | all:: 44 | 45 | $(shell mkdir -p $(objdir)) 46 | 47 | include Makeoptions 48 | include Makefunctions 49 | include Makeconfig 50 | include Build $(wildcard $(sort */Build)) 51 | -include $(objdir)/*.d 52 | include Makerules 53 | 54 | all:: $(TARGETS) 55 | 56 | clean:: 57 | $(call describe-target,CLEAN,$(objdir)) 58 | -rm -rf $(objdir) 59 | 60 | realclean: clean 61 | -rm -f TAGS tags GTAGS GRTAGS GPATH 62 | 63 | TAGS: 64 | $(call describe-target,TAGS) 65 | rm -f TAGS; find . -name '*.[ch]' | xargs etags -a 66 | 67 | tags: 68 | $(call describe-target,tags) 69 | rm -f tags; find . -name '*.[ch]' | xargs ctags -a 70 | 71 | gtags: 72 | $(call describe-target,gtags) 73 | gtags -i 74 | 75 | PHONIES += all clean TAGS tags gtags 76 | 77 | .PHONY: $(PHONIES) 78 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The Universal Permissive License (UPL), Version 1.0 2 | 3 | Subject to the condition set forth below, permission is hereby granted 4 | to any person obtaining a copy of this software, associated 5 | documentation and/or data (collectively the "Software"), free of charge 6 | and under any and all copyright rights in the Software, and any and all 7 | patent rights owned or freely licensable by each licensor hereunder 8 | covering either (i) the unmodified Software as contributed to or 9 | provided by such licensor, or (ii) the Larger Works (as defined below), 10 | to deal in both 11 | 12 | (a) the Software, and 13 | (b) any piece of software and/or hardware listed in the lrgrwrks.txt 14 | file if one is included with the Software (each a “Larger Work” to which 15 | the Software is contributed by such licensors), 16 | 17 | without restriction, including without limitation the rights to copy, 18 | create derivative works of, display, perform, and distribute the 19 | Software and make, use, sell, offer for sale, import, export, have made, 20 | and have sold the Software and the Larger Work(s), and to sublicense the 21 | foregoing rights on either these or other terms. 22 | 23 | This license is subject to the following condition: 24 | The above copyright notice and either this complete permission notice or 25 | at a minimum a reference to the UPL must be included in all copies or 26 | substantial portions of the Software. 27 | 28 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 29 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 30 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 31 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 32 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 33 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 34 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 35 | Licensed under the Universal Permissive License v 1.0 as shown at 36 | http://oss.oracle.com/licenses/upl. 37 | -------------------------------------------------------------------------------- /Makeconfig: -------------------------------------------------------------------------------- 1 | # Determine properties of the system and write a config.h. 2 | # 3 | # Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Universal Permissive License v 1.0 as shown at 6 | # http://oss.oracle.com/licenses/upl. 7 | # 8 | # Licensed under the GNU General Public License (GPL), version 2. See the file 9 | # COPYING in the top level of this tree. 10 | 11 | # The configuration header file. 12 | 13 | CONFIG_H = $(objdir)/config.h 14 | 15 | # Generate a makefile rule to check for the presence of SYMBOL 16 | # in LIBRARY and emit an appropriate header file fragment into 17 | # a file under $(objdir)/.config. 18 | # 19 | # The first argument must be suitable for a filename fragment, 20 | # for a makefile rule name and for a #define. 21 | # 22 | # Syntax: $(call check-symbol,name,symbol,library) 23 | define check-symbol-rule 24 | $(objdir)/.config/config.$(1).h: $(objdir)/.config/.dir.stamp 25 | if echo 'void $(2)(); int main(void) { $(2)(); }' | \ 26 | $(CC) $(CFLAGS) $(LDFLAGS) -o /dev/null -x c - -l$(3) >/dev/null 2>&1; then \ 27 | echo '#define HAVE_$(1) 1' > $(objdir)/.config/config.$(1).h; \ 28 | else \ 29 | echo '/* #undef HAVE_$(1) */' > $(objdir)/.config/config.$(1).h; \ 30 | fi 31 | 32 | $(CONFIG_H): $(objdir)/.config/config.$(1).h 33 | endef 34 | 35 | # Generate a makefile rule to check for the presence of HEADER 36 | # and emit an appropriate header file fragment into a file 37 | # under $(objdir)/.config. 38 | # 39 | # The first argument must be suitable for a filename fragment, 40 | # for a makefile rule name and for a #define. 41 | # 42 | # Syntax: $(call check-header-rule,name,header) 43 | define check-header-rule 44 | $(objdir)/.config/config.$(1).h: $(objdir)/.config/.dir.stamp 45 | if echo '#include <$(2)>' | \ 46 | $(CC) $(CFLAGS) $(LDFLAGS) -c -o /dev/null -x c - >/dev/null 2>&1; then \ 47 | echo '#define HAVE_$(1)_H 1' > $(objdir)/.config/config.$(1).h; \ 48 | else \ 49 | echo '/* #undef HAVE_$(1)_H */' > $(objdir)/.config/config.$(1).h; \ 50 | fi 51 | 52 | $(CONFIG_H): $(objdir)/.config/config.$(1).h 53 | endef 54 | 55 | $(objdir)/.config/config.bfd_section_size.h: $(objdir)/.config/.dir.stamp 56 | if printf '#include \n#include \nint main (void) { asection *foo = NULL; printf ("%%li", bfd_section_size (foo)); }' | \ 57 | $(CC) $(CFLAGS) $(LDFLAGS) -c -o /dev/null -x c - >/dev/null 2>&1; then \ 58 | echo '#define HAVE_ONE_ARG_BFD_SECTION_SIZE 1' > $(objdir)/.config/config.bfd_section_size.h; \ 59 | else \ 60 | echo '/* #undef HAVE_ONE_ARG_BFD_SECTION_SIZE */' > $(objdir)/.config/config.bfd_section_size.h; \ 61 | fi 62 | $(CONFIG_H): $(objdir)/.config/config.bfd_section_size.h 63 | 64 | $(objdir)/.config/.dir.stamp: 65 | mkdir -p $(objdir)/.config 66 | touch $(objdir)/.config/.dir.stamp 67 | 68 | $(CONFIG_H): 69 | echo '/* This file is automatically generated. */' > $(objdir)/config.h 70 | cat $(objdir)/.config/*.h >> $(objdir)/config.h 2>/dev/null || true 71 | 72 | $(eval $(call check-symbol-rule,MMAP,mmap,c)) 73 | $(eval $(call check-symbol-rule,PREAD,pread,c)) 74 | $(eval $(call check-symbol-rule,BSEARCH_R,bsearch_r,c)) 75 | $(eval $(call check-header-rule,BYTESWAP,byteswap.h)) 76 | $(eval $(call check-header-rule,ENDIAN,endian.h)) 77 | -------------------------------------------------------------------------------- /Makefunctions: -------------------------------------------------------------------------------- 1 | # Functions used by the individual Build files. 2 | # 3 | # Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Universal Permissive License v 1.0 as shown at 6 | # http://oss.oracle.com/licenses/upl. 7 | # 8 | # Licensed under the GNU General Public License (GPL), version 2. See the file 9 | # COPYING in the top level of this tree. 10 | 11 | # A variable expanding to the directory of the currently included makefile 12 | # fragment. 13 | 14 | current-dir = $(dir $(lastword $(MAKEFILE_LIST))) 15 | 16 | # Functions to generate the name of an object file and source file for a 17 | # given primary. 18 | # Syntax: $(call *-name,primary,filename) 19 | 20 | obj-name = $(addprefix $(objdir)/$(subst /,-,$($(1)_DIR))-,$(subst /,-,$(2:.c=.o))) 21 | src-name = $(addprefix $($(1)_DIR),$(2)) 22 | 23 | # If 'verbose' is not set, this echoes a description and truncated target (or 24 | # other identifier) for this rule. 25 | # Syntax: $(call describe-target,description,optional names) 26 | define describe-target 27 | $(if $(filter-out $(verbose),no),,$(foreach name,$(2),printf '%s: %s\n' '$(1)' '$(name)';)) 28 | endef 29 | 30 | # Describe an installation target. All paths on the 'names' are stripped. 31 | # Syntax: $(call describe-install-target,directory,names) 32 | define describe-install-target 33 | $(call describe-target,INSTALL,$(addprefix $(1)/,$(notdir $(2)))) 34 | endef 35 | 36 | # Rule to build a C source file. 37 | # Syntax: $(call cc-template,primary,filename-without-dir,optional flags) 38 | 39 | cc-dependencies = -MP -MMD -MT $(obj-name) 40 | 41 | define cc-template 42 | $(obj-name): $(src-name) $(foreach dep,$($(1)_SRCDEPS),$(call src-name,$(1),$(dep))) $(CONFIG_H) 43 | $(call describe-target,CC,$(src-name)) 44 | $(CC) $(CPPFLAGS) $($(1)_CPPFLAGS) $(filter-out $($(1)_NOCFLAGS),$(CFLAGS) $($(1)_CFLAGS) $(3)) $(cc-dependencies) -c -o $(obj-name) $(src-name) 45 | endef 46 | 47 | # Rule to build a build library, and all its sources. 48 | # Syntax: $(call build-lib-template,primary) 49 | 50 | define build-lib-template 51 | $(objdir)/build-$($(1)_TARGET).a: $(foreach source,$($(1)_SOURCES),$(call obj-name,$(1),$(source))) \ 52 | $(foreach dep,$(filter-out %.o,$($(1)_DEPS)),$(addprefix $(objdir)/,$(dep))) \ 53 | $(foreach dep,$(filter %.o,$($(1)_DEPS)),$(call obj-name,$(1),$(dep))) 54 | $(call describe-target,BUILD-AR,$($(1)_TARGET).a) 55 | $(AR) rc $(objdir)/build-$($(1)_TARGET).a $(foreach source,$($(1)_SOURCES),$(call obj-name,$(1),$(source))) 56 | $(foreach post,$($(1)_POST),$(call $(post),$(objdir)/build-$($(1)_TARGET).a)) 57 | 58 | $(foreach file,$(filter-out $($(1)_EXPLICIT),$($(1)_SOURCES)),$(eval $(call cc-template,$(1),$(file),-fPIC))) 59 | endef 60 | 61 | # Rule to build an installable static library from a set of build libraries. 62 | # Syntax: $(call lib-template,primary) 63 | 64 | define lib-template 65 | $(objdir)/$($(1)_TARGET).a: $(foreach build-lib,$($(1)_LIBSOURCES),$(objdir)/build-$($(build-lib)_TARGET).a) 66 | $(call describe-target,AR,$($(1)_TARGET).a) 67 | $(AR) rc $(objdir)/$($(1)_TARGET).a $(foreach build-lib,$($(1)_LIBSOURCES),$(foreach source,$($(build-lib)_SOURCES),$(call obj-name,$(build-lib),$(source)))) 68 | $(foreach post,$($(1)_POST),$(call $(post),$(objdir)/$($(1)_TARGET).a)) 69 | endef 70 | 71 | # Rule to build an installable shared library from a set of build libraries. 72 | # Syntax: $(call shlib-template,primary) 73 | 74 | comma := , 75 | define shlib-template 76 | $(objdir)/$($(1)_TARGET).so $(if $($(1)_VERSION),$(objdir)/$($(1)_TARGET).so.$($(1)_VERSION)) $(if $($(1)_SONAME),$(objdir)/$($(1)_SONAME)): \ 77 | $(foreach build-lib,$($(1)_LIBSOURCES),$(objdir)/build-$($(build-lib)_TARGET).a) 78 | $(call describe-target,SHLINK,$(objdir)/$($(1)_TARGET).so) 79 | $(CC) -o $(if $($(1)_VERSION),$(objdir)/$($(1)_TARGET).so.$($(1)_VERSION),$(objdir)/$($(1)_TARGET).so) \ 80 | -shared $(LDFLAGS) $(if $($(1)_SONAME),-Wl$(comma)-soname$(comma)$($(1)_SONAME)) \ 81 | $(if $($(1)_VERSCRIPT),-Wl$(comma)--version-script=$($(1)_VERSCRIPT)) \ 82 | -Wl,--whole-archive $(foreach primary,$(filter-out $($(1)_SECONDARY),$($(1)_LIBSOURCES)),$(objdir)/build-$($(primary)_TARGET).a) -Wl,--no-whole-archive \ 83 | $(foreach secondary,$($(1)_SECONDARY),$(objdir)/build-$($(secondary)_TARGET).a) $($(1)_LIBS) 84 | $(if $($(1)_VERSION),ln -sf $($(1)_TARGET).so.$($(1)_VERSION) $(objdir)/$($(1)_TARGET).so) 85 | $(if $($(1)_SONAME),ln -sf $($(1)_TARGET).so.$($(1)_VERSION) $(objdir)/$($(1)_SONAME)) 86 | $(foreach post,$($(1)_POST),$(call $(post),$(objdir)/$($(1)_TARGET).so$(if $($(1)_VERSION),.$($(1)_VERSION)))) 87 | endef 88 | 89 | # Rule to build a binary, and all its sources. 90 | # Syntax: $(call cmd-template,primary) 91 | 92 | define cmd-template 93 | $(objdir)/$($(1)_TARGET): $(foreach source,$($(1)_SOURCES),$(call obj-name,$(1),$(source))) \ 94 | $(foreach dep,$(filter-out %.o,$($(1)_DEPS)),$(addprefix $(objdir)/,$(dep))) \ 95 | $(foreach dep,$(filter %.o,$($(1)_DEPS)),$(call obj-name,$(1),$(dep))) 96 | $(call describe-target,LINK,$($(1)_TARGET)) 97 | $(CC) $(filter-out $($(1)_NOCFLAGS),$(CFLAGS) $($(1)_CFLAGS)) $(LDFLAGS) -o $(objdir)/$($(1)_TARGET) \ 98 | $(foreach source,$($(1)_SOURCES),$(call obj-name,$(1),$(source))) \ 99 | $($(1)_LIBS) 100 | $(foreach post,$($(1)_POST),$(call $(post),$(objdir)/$($(1)_TARGET))) 101 | 102 | $(foreach file,$(filter-out $($(1)_EXPLICIT),$($(1)_SOURCES)),$(eval $(call cc-template,$(1),$(file)))) 103 | endef 104 | -------------------------------------------------------------------------------- /Makeoptions: -------------------------------------------------------------------------------- 1 | # The implementation of the configurable make options. 2 | # 3 | # Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Universal Permissive License v 1.0 as shown at 6 | # http://oss.oracle.com/licenses/upl. 7 | # 8 | # Licensed under the GNU General Public License (GPL), version 2. See the file 9 | # COPYING in the top level of this tree. 10 | 11 | debugging ?= no 12 | coverage ?= no 13 | verbose ?= no 14 | 15 | PHONIES += help 16 | 17 | help:: 18 | @printf "Options:\n\n" >&2 19 | @printf "make debugging=yes [targets] Disable optimization to make debugger use easier\n" >&2 20 | @printf "make optdebugging=yes [targets] Optimized build with debugging enabled\n" >&2 21 | @printf "make coverage=yes [targets] Turn on test coverage support\n" >&2 22 | @printf "make verbose=yes [target] Enable verbose building\n" >&2 23 | @printf "\n" >&2 24 | 25 | ifneq ($(debugging),no) 26 | override CFLAGS += -O0 -g 27 | endif 28 | 29 | ifneq ($(optdebugging),no) 30 | override CFLAGS += -g 31 | endif 32 | 33 | ifneq ($(coverage),no) 34 | override CFLAGS += -O0 --coverage 35 | override LDFLAGS += --coverage 36 | endif 37 | 38 | ifeq ($(verbose),no) 39 | override MAKEFLAGS += --silent 40 | endif 41 | -------------------------------------------------------------------------------- /Makerules: -------------------------------------------------------------------------------- 1 | # Rules generated from the contents of the Build files. 2 | # 3 | # Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Universal Permissive License v 1.0 as shown at 6 | # http://oss.oracle.com/licenses/upl. 7 | # 8 | # Licensed under the GNU General Public License (GPL), version 2. See the file 9 | # COPYING in the top level of this tree. 10 | 11 | # Trigger the library-building rules. 12 | 13 | PHONIES += build-libs libs shlibs 14 | TARGETS += build-libs libs shlibs 15 | 16 | $(foreach lib,$(BUILDLIBS),$(eval $(call build-lib-template,$(lib)))) 17 | build-libs: $(foreach lib,$(BUILDLIBS),$(objdir)/build-$($(lib)_TARGET).a) 18 | 19 | $(foreach lib,$(LIBS),$(eval $(call lib-template,$(lib)))) 20 | libs: build-libs $(foreach lib,$(LIBS),$(objdir)/$($(lib)_TARGET).a) 21 | 22 | $(foreach lib,$(SHLIBS),$(eval $(call shlib-template,$(lib)))) 23 | shlibs: build-libs $(foreach lib,$(SHLIBS),$(objdir)/$($(lib)_TARGET).so) 24 | 25 | # Trigger the command-building rule. 26 | 27 | PHONIES += cmds 28 | TARGETS += cmds 29 | 30 | $(foreach cmd,$(CMDS),$(eval $(call cmd-template,$(cmd)))) 31 | 32 | cmds: $(foreach cmd,$(CMDS),$(objdir)/$($(cmd)_TARGET)) 33 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | 1.2.0 (not yet released) 2 | ----- 3 | 4 | The codebase is now in GNU style. All files have been renmaed and/or 5 | moved around: upstream consumers can now include if 6 | they want to, or remain with the old if they prefer. 7 | 8 | (containing some obsolescent types used by some 9 | consumers, and a single macro) is no longer used by the libdtrace-ctf 10 | codebase. It is still installed for compatibility, but you are encouraged 11 | to migrate away from it. 12 | 13 | One field in the public API, ctf_lblinfo_t.ctb_typeidx, has been renamed 14 | for clarity to ctf_lblinfo_t.ctb_type (it is not an index: it is a type 15 | ID). CTF labels have no known users, so this should not disturb your code. 16 | 17 | Files generated by libdtrace-ctf on platforms of the opposite endianness 18 | can now be read and used if they were generated on the local system. (As 19 | with version upgrades, this is implemented by flipping the endianness of 20 | the entire file aggressively at open time: cross-endian files thus take a 21 | little longer to open, and -- if stored uncompressed -- consume a little 22 | more memory than native-endian files.) 23 | 24 | The dynamic upgrading machinery can now handle cases where the CTF header 25 | changes between versions. Several new header fields have appeared, among them 26 | cth_cuname (and corresponding ctf_cuname() and ctf_cuname_set() functions), 27 | cth_functidxoff, and cth_objtidxoff. ctf_dump can now dump the headers. 28 | 29 | The dumping machinery has been moved out of ctf_dump into a new ctf_dump() API 30 | in libctf itself, so that other programs can easily produce CTF debugging dumps. 31 | 32 | The internal implementation of the hashtables used by libdtrace-ctf has 33 | changed. As a consequence, libdtrace-ctf now depends on glib 2.x. 34 | 35 | It is no longer necessary to call ctf_update() between calls to ctf_add_*() to 36 | make types added by previous ctf_add_*() calls visible to later calls to those 37 | functions: ctf_update() is now only a tiny convenience function that sets things 38 | up for ctf_discard(), and serialization is handled automatically by the 39 | functions that do writeout. Since ctf_update() is very expensive, this can 40 | result in a huge runtime reduction for programs doing batch type addition. 41 | 42 | ctf_add_type() can now handle replacing forwards with structures *and* 43 | structures with forwards (which just give you the same type back again), so it 44 | can be used to merge several CTF files into one. 45 | 46 | String table management has been completely revamped. The string table is now 47 | sorted and deduplicated. 48 | 49 | There is a new linker infrastructure, ctf_link_*(), that can be used to merge 50 | CTF sections as a whole into larger sections: the linker can pass in its idea of 51 | its external string table, and we will emit appropriate external references 52 | accordingly. The corresponding machinery to allow the function and object info 53 | sections to be reshuffled into place has not yet been impleented. (The new 54 | cth_functidxoff and cth_objtidxoff header fields are part of that). This is 55 | very new and may not be reliable yet. 56 | 57 | All ctf_id_t arguments to ctf_add_*() functions are now validated to ensure 58 | they are existing types. 59 | 60 | You can now change the encoding of an existing type using ctf_add_slice(). 61 | A slice changes the encoding (bitness and offset) of some underlying int, 62 | float, or enum type, but otherwise appears identical at read-time, except 63 | that ctf_type_reference() will return the original int / float / enum. 64 | (Calling ctf_type_reference() on these types was an error before now, so 65 | this should affect no existing callers). The error ECTF_NOTINTFP, raised 66 | if you try to find out the encoding of a type that does not support it, has 67 | changed meaning slightly to include enums as well, now that they support 68 | encodings too. 69 | 70 | The convenience function ctf_add_enum_encoded() allows the addition of an 71 | enumerated type with a particular encoding: under the covers, it adds the 72 | specified enum, if not already present, then creates and hands back a slice 73 | to it. 74 | 75 | The convenience function ctf_add_member_encoded() is like 76 | ctf_add_member_offset() but takes an encoding and emits a new slice. (It 77 | does not look to see if an identical slice already exists, so callers that 78 | care about such things probably want to call ctf_add_slice() directly.) 79 | 80 | The new function ctf_type_aname() is like ctf_type_name() and ctf_type_lname() 81 | except that it returns the new type name in a dynamically-allocated string that 82 | the caller must free, and never truncates it. 83 | 84 | The new function ctf_simple_open() is useful if you want to pass in buffers 85 | to ctf_bufopen() without having to mock up an entire ctf_symtab. 86 | 87 | The new function ctf_write_mem() lets you write a CTF file to a new dynamically 88 | allocated buffer, optionally compressing it; ctf_arc_write_fd() allows you 89 | to write archives to already-open file descriptors. 90 | 91 | ctf_open() and ctf_fdopen() now use BFD to read binaries, and accept a new 92 | target argument which is either NULL or a BFD target name. There are new 93 | lower-level functions ctf_bfdopen() and ctf_bfdopen_ctfsect(). 94 | 95 | CTF archives are now more central. The opening functions just cited all return a 96 | ctf_archive_t, not a ctf_file_t, even if they are called on raw CTF files or on 97 | binaries with a .ctf section whose content is a raw CTF file. This appears to 98 | users as a CTF archive with a single member named _CTF_SECTION (or NULL, for 99 | sort), which you can open with ctf_arc_open_by_name(). ctf_close() now accepts 100 | either a ctf_file_t or a ctf_archive_t: if CTF_CLOSE_NEW_API is #defined at 101 | include time, the prototype changes to a ctf_archive_t, but the function accepts 102 | either. There is also a new function ctf_arc_open_by_name_sections() which 103 | allows you to explicitly specify the string and symbol sections associated with 104 | a CTF file when opening it out of an archive, in case the string and symbol 105 | tables set by ctf_open() and ctf_fdopen() are not right for your use case. 106 | 107 | Because it might be annoying to drag around an archive just to keep track of it 108 | to close it, the new function ctf_get_arc() returns the archive from which a CTF 109 | file was opened, so you can close it easily. 110 | 111 | libdtrace-ctf now works (with limitations) on non-ELF platforms and platforms 112 | not supporting mmap() or pread(). 113 | 114 | 1.1.0 115 | ----- 116 | 117 | Add ctf_add_struct_sized() and ctf_add_union_sized(), allowing callers 118 | to specify a size for structs and unions which is larger than the size 119 | computed by aligning the last element. This is useful if the compiler 120 | adds extra padding beyond that which would be added by the last element 121 | alone. 122 | 123 | Fix a bug causing the heap to be mprotect()ed if a CTF section was passed 124 | in to ctf_bufopen() containing contents generated by libdtrace-ctf 1.0.0 125 | or above. 126 | [Bug introduced in 1.0.0] 127 | 128 | Work around some very minor CTF-generation bugs seen in CTF in the wild, 129 | converting a few type conflict errors into silent continued operation. 130 | 131 | ctf_dump now shows the size of each type. 132 | 133 | 1.0.0 134 | ----- 135 | 136 | CTF format v2, boosting the number of types from 32767*2 to 2^31*2, the 137 | number of struct and union members and enumerated values from 2^10 to 138 | 2^25, and the number of type kinds to 64 (for future expansion). 139 | 140 | The ABI is unchanged, and v1 CTF files will be transparently upgraded to 141 | v2 at open time, with unchanged type IDs. Newly-created files will have 142 | type IDs in child containers starting at 0x80000000 (printf()s should use 143 | %lx or %lu, not %i, to avoid spuriously negatively-signed type IDs). 144 | 145 | We do not support using v1 files as the parent of v2 files, nor vice versa, 146 | and it is unlikely to work well. 147 | 148 | Changes likely to be of interest only to people using the API to directly access 149 | CTF files without going through the library: 150 | 151 | API changes, limit constants: 152 | - CTF_MAX_TYPE, CTF_MAX_PTYPE, CTF_MAX_VLEN, CTF_MAX_SIZE, 153 | CTF_MAX_LSIZE_SENT, CTF_LSTRUCT_THRESH now relate to v2 limits, not v1 154 | - CTF_MAX_TYPE_V1, CTF_MAX_PTYPE_V1, CTF_MAX_VLEN_V1, CTF_MAX_SIZE_V1, 155 | CTF_MAX_LSIZE_SENT_V1, CTF_LSTRUCT_THRESH_V1: New. 156 | - CTF_MAX_LSIZE, CTF_MAX_INTOFF, CTF_MAX_INTBITS: Removed (unused). 157 | - CTF_K_MAX is boosted to 63 from 31. 158 | 159 | API changes, file format accessors: 160 | - CTF_INFO_KIND, CTF_INFO_ISROOT, CTF_INFO_VLEN: Replaced with 161 | CTF_V1_INFO_* and CTF_V2_INFO_*. 162 | - CTF_TYPE_TO_INDEX / CTF_INDEX_TO_TYPE: Replaced with CTF_V1_* and CTF_V2_*. 163 | - CTF_TYPE_INFO: relates to v2 now. No v1 equivalent. 164 | - CTF_TYPE_ISPARENT / CTF_TYPE_ISCHILD: replaced with ctf_type_isparent() / 165 | ctf_type_ischild() functions. 166 | 167 | API changes, structure changes: 168 | - struct ctf_stype, ctf_stype, ctf_array now relate to v2, not v1 169 | - struct ctf_stype_v1, ctf_type_v1, ctf_array_v1: New. 170 | - struct ctf_lmember, ctf_member: Removed, replaced with _v1 and _v2 171 | variants: the typedef persists, now relating to v2, not v1. 172 | - The vlen for CTF_K_FUNCTION, CTF_K_ARRAY, CTF_K_STRUCT and CTF_K_UNION 173 | has changed. 174 | - Threshold changes mean that some types will be placed into ctf_stype 175 | and some members into ctf_member where previously ctf_type and 176 | ctf_lmember were needed. 177 | 178 | ctf_ar now extracts CTF data from CTF archives without recompressing or changing 179 | it. It supports a -u option to force opening and recompressing: note that this 180 | will upgrade CTFv1 data to v2 in the process. 181 | 182 | 0.8.1 183 | ----- 184 | 185 | Fix bug causing loss of all types in a CTF container if the container has 186 | a parent and ctf_rollback() is called. (Only the types since the last 187 | ctf_snapshot() should be removed, not every type.) 188 | 189 | 0.8.0 190 | ----- 191 | 192 | Support for ARM64. 193 | 194 | A new #define is provided, CTF_CHAR, which can be used to produce a char type 195 | with the same signedness as the system's native char type. 196 | 197 | 0.7.0 198 | ----- 199 | 200 | Support creation and use of "CTF archives" that contain any number of CTF files 201 | in an efficient, endian-independent, mmap()able representation. A new tool, 202 | ctf_ar, supports listing and extraction of CTF files from these archives, 203 | for debugging. 204 | 205 | libdtrace-ctf now supports not only reading compressed archives but also their 206 | creation, through the new function ctf_compress_write(). 207 | 208 | 0.6.0 209 | ----- 210 | 211 | Support multiple types with the same name where only one is a root type better 212 | (as seen in the definition of bitfields). This introduces additional error 213 | checking which may break situations in which multiple root types with the same 214 | name but different definitions. All such situations are undefined: previously, 215 | libdtrace-ctf would have returned either the last such type defined or a random 216 | one depending on which API function was used. 217 | 218 | 0.5.0 219 | ----- 220 | 221 | libdtrace-ctf is now compatible with big-endian systems (like SPARC). 222 | 223 | 0.4.3 224 | ----- 225 | 226 | A pair of new functions, ctf_snapshot() and ctf_rollback(), provide type- 227 | and-variable discarding functionality like that ctf_discard() did, but 228 | without the expense of calling ctf_update() to get a point to discard to. 229 | 230 | 0.4.2 231 | ----- 232 | 233 | The build system is now compatible with GNU Make 4.0. 234 | 235 | 0.4.1 236 | ----- 237 | 238 | A bug causing reads of unintialized memory is fixed. 239 | 240 | ctf_dump is much more useful, dumping information on structure and union members 241 | recursively, and supporting a couple of extra flags that may be useful when 242 | driving ctf_dump from another process. 243 | 244 | 0.4.0 245 | ----- 246 | 247 | ctf_dump, a new CTF dumping tool, is introduced. It is meant for debugging, 248 | so it is built by default, but not installed. 249 | 250 | A new function for iterating over variables stored in a CTF file, 251 | ctf_variable_iter(), is introduced. Iteration fails immediately if 252 | this is a child CTF file with no associated parent. 253 | 254 | 0.3.3 255 | ----- 256 | 257 | A failed ctf_lookup_by_id() of a type which should have been found in a parent 258 | container now sets the errno on the CTF file on which the lookup was initiated, 259 | rather than mistakenly setting it on its parent. 260 | 261 | 0.3.2 262 | ----- 263 | 264 | CTF sections are now named .ctf by default, not .dtrace_ctf: this package is 265 | not dependent on DTrace. 266 | 267 | 0.3 268 | --- 269 | 270 | First release. 271 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | libdtrace-ctf is a port of the Solaris Compact Type Format library to Linux. 2 | Its file format is similar to but not compatible with Solaris CTF files, but 3 | its public API is source-compatible, to ease porting of libctf users to 4 | Linux. 5 | 6 | It's meant for the use of DTrace for Linux, but is dual-licensed under the GPL 7 | in order that it may be used in the Linux kernel build process, and potentially 8 | in any other projects that may find it useful. 9 | -------------------------------------------------------------------------------- /README.build-system: -------------------------------------------------------------------------------- 1 | The dtrace build system is intended to take some of the repetitive pain 2 | out of make. The build system's components are: 3 | 4 | - GNUmakefile: the top-level file. Sets some variables, runs 5 | everything else 6 | 7 | - Makefunctions: defines a few functions that other files can 8 | use, and a set of templates which generate make 9 | rules for building various things. 10 | 11 | - */Build: each of these specifies the building of a library 12 | or a set of commands out of the contents of some 13 | directory. 14 | 15 | - Makerules: this triggers the building of all commands and 16 | libraries specified in the Build files. 17 | 18 | - Makeconfig: this can scan for symbols in libraries, like Autoconf's 19 | AC_CHECK_LIB, and generate a config.h header that describes 20 | whether those symbols are present. (This header file exists 21 | even if no such checks are done, and every compiled C file 22 | is forced to depend on it.) 23 | 24 | The Build files are perfectly normal makefiles, with a few caveats. Firstly, 25 | they are *included* by the top-level makefile, not recursively run by it. 26 | This has advantages (the ability to do proper cross-directory dependencies 27 | and maximum-speed parallel make) and disadvantages (you have to specify 28 | directory names everywhere). 29 | 30 | A note about library construction. Libraries are somewhat unusually built, in 31 | that libraries (be they shared or static) for installation are assembled from 32 | one or more *build libraries* (which are, as usual, put together from one or 33 | more object files). You cannot link against build libraries (or not easily, 34 | anyway), you can only assemble them into larger units. For shared libraries, 35 | some of these build libraries are *primary*, meaning that their entire contents 36 | are included in the shared library whether referenced elsewhere in the shared 37 | library or not: the rest are *secondary*, meaning that their contents are 38 | included only if needed by other parts of the shared library. (Build libraries 39 | containing symbols in the library's public API should generally be primary). By 40 | default, all build libraries in a shared library are primary. 41 | 42 | 43 | This mechanism eases construction of installed libraries from the contents of 44 | more than one directory without requiring Build files to be filled with ugly 45 | cross-directory references, and without sacrificing proper dependency analysis. 46 | 47 | You name build libraries, static and shared libraries, and binaries for 48 | installation by assignment to the following variables in Build files. The names 49 | can be anything you like, and do not have to be the same as the generated output 50 | file, which allows you to have similarly-named output files with different build 51 | rules if you need to do so. 52 | 53 | BUILDLIBS += build library target names 54 | LIBS += static library target names 55 | SHLIBS += shared library target names (can also appear in LIBS for libraries 56 | that should have both static and shared forms) 57 | CMDS += command names 58 | 59 | All of the names in the variables above can have the following variables 60 | associated with them, usually in the same Build file: 61 | 62 | name_DIR := $(current-dir) (obligatory) 63 | name_TARGET = name of library or binary to build for this name, without 64 | directory or any necessary suffix. Build libraries 65 | get 'build-' stuck on the front of this name automatically, 66 | to enforce uniqueness. (obligatory) 67 | name_POST := list of names of Make variables which should be run 68 | after this target is linked: $(1) is the name of the 69 | target just created, with path, and with initial 'build-' 70 | for build libraries. 71 | 72 | Names in the BUILDLIBS and CMDS (the only things produced directly by 73 | compilation of source code) can have the following variables associated with 74 | them: 75 | 76 | name_SOURCES = list of source filenames 77 | name_CPPFLAGS = list of preprocessor flags applying to this target 78 | name_CFLAGS := list of cflags applying only to this target 79 | name_NOCFLAGS := list of cflags which should never be applied to this target, 80 | even if they would otherwise appear in CFLAGS 81 | name_EXPLICIT := list of source files with explicit targets for which 82 | automatic targets should not be generated 83 | name_DEPS := list of explicit dependencies in the build tree 84 | applying to this target's link step 85 | name_SRCDEPS := list of explicit dependencies in the source tree 86 | for (built) source files to be added to the dep 87 | list of every target 88 | 89 | Names in the SHLIBS and CMDS (the only things processed by the linker) can have 90 | the following variables associated with them: 91 | 92 | name_LIBS := list of libraries applying only to this target. Full ld syntax, 93 | including -l. 94 | 95 | Names in the LIBS and SHLIBS must have the following variables associated with 96 | them: 97 | 98 | name_LIBSOURCES := list of BUILDLIBS whose contents go into this target: 99 | by default, all are primary. The leading 'build-' is 100 | added automatically. 101 | 102 | Names in the SHLIBS can have the following variables associated with them: 103 | 104 | name_VERSION := version of this target (strongly recommended) 105 | name_SOANME := soname of this target (strongly recommended) 106 | name_VERSCRIPT := filename of version script for this target 107 | name_SECONDARY := list of secondary BUILDLIBS for this target 108 | 109 | Extra targets with custom rules can be added as desired by appending to TARGETS 110 | and name_EXPLICIT: libdtrace/ uses this to build object files and .d files. 111 | There is no attempt to automate installation rules, so you'll probably need 112 | install targets here and there. You probably don't want to install build 113 | libraries, but there is no explicit attempt to stop you. 114 | 115 | 116 | Finally, a note on quiet builds. If 'verbose=yes' is not specified at make time, 117 | all command echoing is suppressed. To produce output, two make functions are 118 | provided, 'describe-target' and 'describe-install-target', which you might want 119 | to use in custom rules and install targets. The former, if called like this: 120 | 121 | $(call describe-target,ACTION,file1 file2 file3) 122 | 123 | will print 124 | 125 | ACTION: file1 126 | ACTION: file2 127 | ACTION: file3 128 | 129 | The latter, if called like this: 130 | 131 | $(call describe-install-target,/install/directory,file1 file2 file3) 132 | 133 | will print 134 | 135 | INSTALL: /install/directory/file1 136 | INSTALL: /install/directory/file2 137 | INSTALL: /install/directory/file3 138 | 139 | You probably want to put a single call to 'describe-target' at the top of a 140 | custom rule, and put calls to 'describe-install-target' right before each 141 | invocation of 'install', so that failed installations will indicate their 142 | failure by the last line they print. (This is notably annoying: in the future, 143 | it may be automated away.) 144 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NOTE 2 | 3 | This project is superseded by the CTF support in GNU binutils: it is only 4 | used by old versions of its dependent projects. It is still published here 5 | in case a bugfix is needed to support one of those projects. 6 | 7 | The project has been merged into GNU binutils 2.33 and GCC 12; as of 8 | binutils 2.36 it is much more capable and can deduplicate CTF more reliably 9 | and rapidly than any other implementation (to my knowledge). Please submit 10 | changes to [binutils upstream](https://sourceware.org/binutils/). (Please 11 | indicate if you need those changes in an old project that still uses 12 | libdtrace-ctf, but all changes should flow in through GNU binutils first.) 13 | 14 | # Linux libdtrace-ctf 15 | 16 | libdtrace-ctf is a port of the Solaris Compact Type Format library to Linux. 17 | It's meant to be used with DTrace for Linux. 18 | Its file format is similar to but not compatible with Solaris CTF files. 19 | The public API is source-compatible, to ease adoption of Linux for libctf users. 20 | 21 | The source has been available at 22 | [oss.oracle.com](https://oss.oracle.com/git/gitweb.cgi?p=libdtrace-ctf.git;a=tags), 23 | as a git repository with full git history. 24 | By posting the source here on github.com, we hope to increase the visibility for our work 25 | and to make it even easier for people to access the source. 26 | We will also use this repository to work with developers in the Linux community. 27 | 28 | See the [dtrace-utils README](https://github.com/oracle/dtrace-utils) 29 | for more information on how to build DTrace utilities 30 | with `libdtrace-ctf` for the Linux kernel. 31 | 32 | ## License 33 | 34 | libdtrace-ctf is licensed under either the GPLv2+ or the UPL 1.0 (Universal 35 | Permissive License). A copy of the GPLv2 license is included in this repository 36 | as the COPYING file. A copy of the UPL 1.0 license is included in this repository 37 | as the LICENSE.txt file. 38 | 39 | ## Dependencies 40 | 41 | Dependencies may include: 42 | - elfutils (to the extent that elfutils is utilized, libdtrace-ctf uses only 43 | those portions of elfutils that are licensed LGPLv3) 44 | - zlib 45 | 46 | ## Build 47 | 48 | Build as follows: 49 | 50 | ``` 51 | $ make 52 | $ sudo make install 53 | ``` 54 | 55 | For more detail, see [README.build-system](README.build-system). 56 | 57 | ## Questions 58 | 59 | For questions, check the 60 | [dtrace-devel mailing list](https://oss.oracle.com/mailman/listinfo/dtrace-devel). 61 | 62 | ## Contributing 63 | 64 | This project is not accepting external contributions at this time. For bugs or enhancement requests, please file a GitHub issue unless it’s security related. When filing a bug remember that the better written the bug is, the more likely it is to be fixed. If you think you’ve found a security vulnerability, do not raise a GitHub issue and follow the instructions in our [security policy](./SECURITY.md). 65 | 66 | Please contact us via the mailing list above. 67 | 68 | The source code for libdtrace-ctf is published here without support. Compiled binaries are provided as part of Oracle Linux, 69 | which is [free to download](http://www.oracle.com/technetwork/server-storage/linux/downloads/index.html), distribute and use. 70 | Support for libdtrace-ctf is included in Oracle Linux support subscriptions. Individual packages and updates are available on the [Oracle Linux yum server](https://yum.oracle.com). 71 | 72 | ## Security 73 | 74 | Please consult the [security guide](./SECURITY.md) for our responsible security vulnerability disclosure process 75 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Reporting security vulnerabilities 2 | 3 | Oracle values the independent security research community and believes that 4 | responsible disclosure of security vulnerabilities helps us ensure the security 5 | and privacy of all our users. 6 | 7 | Please do NOT raise a GitHub Issue to report a security vulnerability. If you 8 | believe you have found a security vulnerability, please submit a report to 9 | [secalert_us@oracle.com][1] preferably with a proof of concept. Please review 10 | some additional information on [how to report security vulnerabilities to Oracle][2]. 11 | We encourage people who contact Oracle Security to use email encryption using 12 | [our encryption key][3]. 13 | 14 | We ask that you do not use other channels or contact the project maintainers 15 | directly. 16 | 17 | Non-vulnerability related security issues including ideas for new or improved 18 | security features are welcome on GitHub Issues. 19 | 20 | ## Security updates, alerts and bulletins 21 | 22 | Security updates will be released on a regular cadence. Many of our projects 23 | will typically release security fixes in conjunction with the 24 | [Oracle Critical Patch Update][3] program. Additional 25 | information, including past advisories, is available on our [security alerts][4] 26 | page. 27 | 28 | ## Security-related information 29 | 30 | We will provide security related information such as a threat model, considerations 31 | for secure use, or any known security issues in our documentation. Please note 32 | that labs and sample code are intended to demonstrate a concept and may not be 33 | sufficiently hardened for production use. 34 | 35 | [1]: mailto:secalert_us@oracle.com 36 | [2]: https://www.oracle.com/corporate/security-practices/assurance/vulnerability/reporting.html 37 | [3]: https://www.oracle.com/security-alerts/encryptionkey.html 38 | [4]: https://www.oracle.com/security-alerts/ 39 | -------------------------------------------------------------------------------- /TODO.org: -------------------------------------------------------------------------------- 1 | * Efficiency 2 | ** DONE Move to a decent hash? 3 | Currently, there are two distinct classes of hashtable used in libctf: 4 | 5 | - ctf_hash hashes, used for hashes of data read from CTF sections only. These 6 | do not support element deletion and have a fixed maximum size, but have a 7 | reasonably good hash function. They are fundamental to the performance of 8 | CTF in normal operation (when the hashes indeeed do not change in size). 9 | 10 | - handrolled dtd hashes, used for the ctf_dthash and ctf_dvhash, i.e. for 11 | hashes of dynamic data in CTF files under construction. These support 12 | deletion (very crudely) but have a fixed bucket count (sigh) and in the case 13 | of ctf_dthash have an astonishingly crude hash function, which nonetheless 14 | probably works. 15 | 16 | The latter class of hash has two instances at present, which share no code at 17 | all. This is disgusting. Their deletion support is also crude in the extreme 18 | and very slow -- though as it is only used when ctf_discard() is called, and 19 | that is only called on the occasion of a type error, this is probably not 20 | important. 21 | 22 | ** DONE adapt to endianness changes 23 | * Reliability 24 | ** TODO Add a testsuite. 25 | OpenSolaris doesn't come with one, as far as I can tell. 26 | 27 | It is true that the only fundamental question is whether dwarf2ctf and dtrace 28 | work, and the latter has a testsuite and the former is *itself* a pretty 29 | effective testsuite by virtue of the sheer volume of data it must chew through 30 | --- but the dtrace testsuite is not publically available, and waiting twenty 31 | minutes to see if you've introduced a bug is terribly tiresome. 32 | ** TODO Add a feature flag system to allow backwardly-incompatible changes. 33 | Right now we have no way to add extra validation because existing codebases 34 | might be broken (and have to revert one commit on every release branch as a 35 | consequence). Add a feature-flag system to allow codebases to certify that they 36 | are ready for such changes in a fine-grained manner. 37 | 38 | ** TODO validate all type IDs added 39 | Right now, we do not validate type IDs passed in (e.g. for types containing 40 | references to other types) unless we need the types for some other purpose 41 | in the addition function. So you can pass in garbage, and cause all sorts of 42 | chaos on load. We shuld validate the damn things. Yes, this stops people 43 | adding a forward before adding the thing it is a forward to, but nobody 44 | should be doing anything so crazy. 45 | 46 | * Features 47 | ** TODO Add function-signature mapping 48 | Required for typed args in FBT and systrace. 49 | 50 | * Minor 51 | ** Refactor second init_types() loop 52 | Most of the entries can be collapsed to one. 53 | -------------------------------------------------------------------------------- /UNTESTED: -------------------------------------------------------------------------------- 1 | The following features and functions have not been tested since the Solaris era, 2 | and thus are relatively likely to be broken. 3 | 4 | Caveat emptor applies. 5 | 6 | Untested features: 7 | 8 | - Labels, including parent labels and parent names in the CTF header 9 | - the ELF string table (CTF_STRTAB_1) 10 | - the function info section and symbol table handling: ctf_add_function(), 11 | ctf_func_info(), ctf_func_args(), ctf_lookup_by_symbol(), init_symtab(), 12 | sym_to_elf64(), ctf_nsyms, ctf_sxlate 13 | - ctf_add_type() of enums; ctf_enum_name() and ctf_enum_value() 14 | - declarator handling around the restrict qualifier 15 | - some codepaths to do with anonymous struct/union members 16 | - ctf_version() (which we can possibly drop? seems like it might be useful in 17 | future though) 18 | - reuse of integer/float variable names by bitfields (all dwarf2ctf's 19 | bitfields are unnamed types) 20 | -------------------------------------------------------------------------------- /doc/ctf-format: -------------------------------------------------------------------------------- 1 | CTF FILE FORMAT 2 | --------------- 3 | 4 | Format: v2 + slices (current v3, trunk pre-1.2) 5 | 6 | A CTF file ("container", since it is usually not a file, but an ELF section or 7 | something or that sort) is divided into a number of sections internally, 8 | identified by offset from the header. In order, the sections are: 9 | 10 | - Type label section 11 | - Data object section 12 | - Function info section 13 | - Variable info section 14 | - Data type section 15 | - String table 16 | 17 | We'll consider these in order of importance (not the same as order in the file). 18 | 19 | Other things in the header: 20 | - a preamble containing a magic number (used to determine container 21 | endianness: libctf will endian-flip foreign-endian containers into the 22 | native endianness at open time), a version number, whose current value is 23 | the CTF_VERSION constant, and a set of CTF_F global flags 24 | - a parent container name and label, which indicates (in some 25 | consumer-dependent way) the name of the container containing types whose ID 26 | has its MSB turned on (the "parent container"): it is only nonzero if this 27 | container is not itself a parent. This allows types to be shared between 28 | containers: with one container being the parent of potentially many others. 29 | (The parent label has space allocated in the header, but is not used by any 30 | code in libctf at present.) 31 | 32 | This does mean that a container cannot be used both as a parent and as a child 33 | container at the same time, because type IDs referring to types within the same 34 | container will have their MSB turned on if this was constructed as a parent 35 | container. While there is a parent name and parent label in the header, it is 36 | purely up to the CTF consumer and convention how this is interpreted: neither 37 | libctf nor the format prohibits ctf_import()ing any container at all as a parent 38 | container, though you should in general import the same parent at consumption 39 | time as you did when you generated the container, or things wil misbehave. 40 | 41 | 42 | Data type section 43 | ----------------- 44 | 45 | This is the core section in a CTF file, an array of variable-length entries, 46 | each entry a struct ctf_stype or struct ctf_type followed by optional 47 | variable-length data. Each array index is transformed into a type ID by 48 | flipping on the MSB iff this is a parent type container. These type IDs are how 49 | types are referenced within CTF containers. The ID of each type is not stored 50 | witih the type, but is implied by its array index. 51 | 52 | The ctf_type_t and ctf_stype_t act as a discriminated union with an identical 53 | first few members: 54 | 55 | typedef struct ctf_stype 56 | { 57 | uint32_t ctt_name; /* Reference to name in string table. */ 58 | uint32_t ctt_info; /* Encoded kind, variant length (see below). */ 59 | union 60 | { 61 | uint32_t ctt_size; /* Size of entire type in bytes. */ 62 | uint32_t ctt_type; /* Reference to another type. */ 63 | }; 64 | } ctf_stype_t; 65 | 66 | All types are represented by an instance of one of these structures: ctt_name is 67 | 0 for unnamed types, while ctt_info is a tiny bitfielded structure accessed via 68 | masking: 69 | 70 | ------------------------ 71 | ctt_info: | kind | isroot | vlen | 72 | ------------------------ 73 | 31 26 25 24 0 74 | where 75 | 76 | kind: a CTF_K_* constant indicating whether this type is an int, a float, an array, 77 | a pointer, a structure or what-have-you (see below) 78 | isroot: is 1 if this type has a name, 0 otherwise 79 | vlen: the length of a kind-specific variable data region ("variant data") which 80 | immediately follows the ctf_stype or ctf_type structure, and contains 81 | type-kind-specific properties (array length, an array of structure 82 | members, or whatever). The data in the vlen region is the closest thing to 83 | most of the attributes used by DWARF to describe types. In general, only 84 | kinds for which the vlen is actually variable can be trusted to have 85 | useful values in this field: for all other kinds, the vlen is meaningless 86 | and is usually hardwwiired for that kind where needed. ctf.h defines the 87 | currently-valid set of kinds: 88 | 89 | #define CTF_K_UNKNOWN 0 /* Unknown type (used for padding). */ 90 | #define CTF_K_INTEGER 1 /* Variant data is CTF_INT_DATA (see below). */ 91 | #define CTF_K_FLOAT 2 /* Variant data is CTF_FP_DATA (see below). */ 92 | #define CTF_K_POINTER 3 /* ctt_type is referenced type. */ 93 | #define CTF_K_ARRAY 4 /* Variant data is single ctf_array_t. */ 94 | #define CTF_K_FUNCTION 5 /* ctt_type is return type, variant data is 95 | list of argument types (unsigned short's for v1, 96 | uint32_t's for v2). */ 97 | #define CTF_K_STRUCT 6 /* Variant data is list of ctf_member_t's. */ 98 | #define CTF_K_UNION 7 /* Variant data is list of ctf_member_t's. */ 99 | #define CTF_K_ENUM 8 /* Variant data is list of ctf_enum_t's. */ 100 | #define CTF_K_FORWARD 9 /* No additional data; ctt_name is tag. */ 101 | #define CTF_K_TYPEDEF 10 /* ctt_type is referenced type. */ 102 | #define CTF_K_VOLATILE 11 /* ctt_type is base type. */ 103 | #define CTF_K_CONST 12 /* ctt_type is base type. */ 104 | #define CTF_K_RESTRICT 13 /* ctt_type is base type. */ 105 | #define CTF_K_SLICE 14 /* Variant data is a ctf_slice_t. */ 106 | 107 | #define CTF_K_MAX 63 /* Maximum possible (V2) CTF_K_* value. */ 108 | 109 | Most of these obviously relate directly to specific C types: the only strange 110 | one is 'slice', which allows you to take an integral type and modify its 111 | bitness, for easy construction of bitfields (a slice of a CTF_K_ENUM is the only 112 | way to specify an enum bitfield). 113 | 114 | 115 | Looking at the rest of the ctf_stype_t, the ctt_size / ctt_type union is a trick 116 | to reduce sizes. Most type-kinds that refer to another type (like pointers, or 117 | cv-quals) have a fixed size, defined by the platform ABI (libctf calls this the 118 | 'machine model'): most types that have a variable size do not refer to another 119 | type: all the most voluminous type kinds either do one or the other. So the 120 | ctt_size / ctt_type contains whichever of these is applicable to the type in 121 | question. (A few kinds, like structures or function pointers, refer to more than 122 | one type ID: in this case, relevant type IDs are carried in the vlen data.) 123 | 124 | For very large types the ctf_stype is not enough: the size of types can exceed 125 | that representable by a uint32_t. For these, we use a ctf_type_t instead: 126 | 127 | typedef struct ctf_type 128 | { 129 | uint32_t ctt_name; /* Reference to name in string table. */ 130 | uint32_t ctt_info; /* Encoded kind, variant length (see below). */ 131 | union 132 | { 133 | uint32_t ctt_size; /* Always CTF_LSIZE_SENT. */ 134 | uint32_t ctt_type; /* Do not use. */ 135 | }; 136 | uint32_t ctt_lsizehi; /* High 32 bits of type size in bytes. */ 137 | uint32_t ctt_lsizelo; /* Low 32 bits of type size in bytes. */ 138 | } ctf_type_t; 139 | 140 | As noted above, this overlays on top of the ctf_stype_t, so almost all code can 141 | just deal directly with whichever it prefers and check ctt_size to see if this 142 | is a ctf_type or ctf_stype. You distinguish a ctf_type_t from a ctf_stype_t 143 | because ctf_type_t has ctt_size == CTF_LSIZE_SENT (which is an invalid value for 144 | a type ID). 145 | 146 | Structure members use a similar trick. Almost all the time, the size of the 147 | structure (the ctt_size) is less than 2^32 bytes, and the variable data is an 148 | array of ctf_member_t's: 149 | 150 | typedef struct ctf_member_v2 151 | { 152 | uint32_t ctm_name; /* Reference to name in string table. */ 153 | uint32_t ctm_offset; /* Offset of this member in bits. */ 154 | uint32_t ctm_type; /* Reference to type of member. */ 155 | } ctf_member_t; 156 | 157 | But if the structure is really huge (above CTF_LSTRUCT_THRESH bytes in length), 158 | the ctt_size overflows the range of the ctm_offset, and every member in this 159 | structure is instead described by the larger ctf_lmember_t: 160 | 161 | typedef struct ctf_lmember_v2 162 | { 163 | uint32_t ctlm_name; /* Reference to name in string table. */ 164 | uint32_t ctlm_offsethi; /* High 32 bits of member offset in bits. */ 165 | uint32_t ctlm_type; /* Reference to type of member. */ 166 | uint32_t ctlm_offsetlo; /* Low 32 bits of member offset in bits. */ 167 | } ctf_lmember_t; 168 | 169 | Unions are identical, and you can represent unnamed structure and union fields 170 | as well with no extensions, by just adding members at the appropriate bit offset 171 | in the containing struct/union (which is how unnamed structs/unions appear to 172 | the programmer, and thus how they should appear to debuggers). 173 | 174 | 175 | Structure members show the general theme for variant data: in most cases, the 176 | variant data is some sort of structure, or an array of structures, or is not 177 | present at all (things like typedefs don't have one): but function types, and 178 | integral and floating-point types, use different sorts of vlen. Function types 179 | use a list of argument types with vlen / sizeof (uint32_t) members, with the 180 | ctt_type being the return type; integer and floating-point types use flags 181 | packed into a single uint32_t in the variant data encoding things like format, 182 | bitness, etc: 183 | 184 | #define CTF_INT_ENCODING(data) (((data) & 0xff000000) >> 24) 185 | #define CTF_INT_OFFSET(data) (((data) & 0x00ff0000) >> 16) 186 | #define CTF_INT_BITS(data) (((data) & 0x0000ffff)) 187 | 188 | #define CTF_INT_DATA(encoding, offset, bits) \ 189 | (((encoding) << 24) | ((offset) << 16) | (bits)) 190 | 191 | #define CTF_INT_SIGNED 0x01 /* Integer is signed (otherwise unsigned). */ 192 | #define CTF_INT_CHAR 0x02 /* Character display format. */ 193 | #define CTF_INT_BOOL 0x04 /* Boolean display format. */ 194 | #define CTF_INT_VARARGS 0x08 /* Varargs display format. */ 195 | 196 | Or, for floats: 197 | 198 | #define CTF_FP_ENCODING(data) (((data) & 0xff000000) >> 24) 199 | #define CTF_FP_OFFSET(data) (((data) & 0x00ff0000) >> 16) 200 | #define CTF_FP_BITS(data) (((data) & 0x0000ffff)) 201 | 202 | #define CTF_FP_DATA(encoding, offset, bits) \ 203 | (((encoding) << 24) | ((offset) << 16) | (bits)) 204 | 205 | /* Variant data when kind is CTF_K_FLOAT is an encoding in the top eight bits. */ 206 | #define CTF_FP_ENCODING(data) (((data) & 0xff000000) >> 24) 207 | 208 | #define CTF_FP_SINGLE 1 /* IEEE 32-bit float encoding. */ 209 | #define CTF_FP_DOUBLE 2 /* IEEE 64-bit float encoding. */ 210 | #define CTF_FP_CPLX 3 /* Complex encoding. */ 211 | #define CTF_FP_DCPLX 4 /* Double complex encoding. */ 212 | #define CTF_FP_LDCPLX 5 /* Long double complex encoding. */ 213 | #define CTF_FP_LDOUBLE 6 /* Long double encoding. */ 214 | #define CTF_FP_INTRVL 7 /* Interval (2x32-bit) encoding. */ 215 | #define CTF_FP_DINTRVL 8 /* Double interval (2x64-bit) encoding. */ 216 | #define CTF_FP_LDINTRVL 9 /* Long double interval (2x128-bit) encoding. */ 217 | #define CTF_FP_IMAGRY 10 /* Imaginary (32-bit) encoding. */ 218 | #define CTF_FP_DIMAGRY 11 /* Long imaginary (64-bit) encoding. */ 219 | #define CTF_FP_LDIMAGRY 12 /* Long double imaginary (128-bit) encoding. */ 220 | 221 | #define CTF_FP_MAX 12 /* Maximum possible CTF_FP_* value */ 222 | 223 | Some of the formats, particularly in the floating-point realm, are somewhat 224 | debatable, and we hope for discussion of what formats are appropriate (C99 225 | complex types appear to be provided for, but not much else). 226 | 227 | It is notable that there are two redundant ways to encode the bitness of 228 | bitfield types, and three redundant ways to encode their offset: you can put 229 | either directly into the encoding, or put it into a slice, or specify the offset 230 | via bit-specific values in the containing structure or union. libctf hides as 231 | much of this as possible by making it appear that slices are the same kind as 232 | the kind they point to, contributing only an encoding: the only difference 233 | between the slice and its underlying type is that you can call 234 | ctf_type_reference() on the slice to get that underlying type, which you cannot 235 | do on an int. 236 | 237 | (In the header alone, but not in the data format, there is an additional 238 | feature: the CTF_CHAR macro is an integral type of the same signedness as the 239 | build target's char type, turning on CTF_INT_SIGNED, nor not, appropriately.) 240 | 241 | 242 | Function info and data object sections 243 | -------------------------------------- 244 | 245 | These two sections, taken together, map 1:1 to the symbols of type STT_OBJECT 246 | and STT_FUNC in an ELF symbol table (usually the symbol table in the ELF object 247 | in which the CTF section is embedded). It is generated by traversing the symbol 248 | table, and whenever a suitable symbol is encountered, adding an entry for it 249 | to the data object or function info sections, depending on whether this is a 250 | STT_OBJECT or STT_FUNC symbol. 251 | 252 | Both producer and consumer must agree on the definition of 'suitable', since 253 | there is no cross-checking here, and if even one symbol is treated differently, 254 | all symbols following it will be misattributed. 255 | 256 | For both STT_FUNC and STT_OBJECT symbols, symbols that have a name that _START_ 257 | or _END_ or that is SHN_UNDEF are omitted; for STT_OBJECT symbols, we further 258 | omit zero-valued SHN_ABS symbols. 259 | 260 | The data object section is an array of type IDs, one entry per suitable entry in 261 | the symbol table: each type ID is the type of the corresponding symbol. 262 | 263 | The function object section is an array of things that (if they were in 264 | structures rather than just a stream of bytes) would look fairly similar to the 265 | variant data for CTF_K_FUNCTION types, described above: 266 | 267 | uint32_t ctt_info; # vlen is number of args 268 | ctf_id_t ctc_return; 269 | ctf_id_t args[vlen]; 270 | 271 | If the last arg is zero, this is a varargs function, and libctf will flip on the 272 | CTF_FUNC_VARARG flag in the funcinfo on return. 273 | 274 | 275 | Variable info section 276 | --------------------- 277 | 278 | This is a very simple section, an array of ctf_varent_t sorted in ascending 279 | strcmp() order by ctv_name. It is used for systems in which there is nothing 280 | resembling a string table, in which address -> name lookup for data objects is 281 | done by machinery outside the purview of CTF, and the caller wants to resolve 282 | string names to types. This covers data objects only: there is currently 283 | nothing resembling the function info section with manual lookup like this. 284 | 285 | 286 | Label section 287 | ------------- 288 | 289 | This section is an array of ctf_lblent, which can be used to tile the type space 290 | into named regions. It might be useful for parallel deduplicators, or to have 291 | distinct parent containers for different regions of the type space (with names 292 | denoted by the label), or such things. 293 | 294 | 295 | String table 296 | ------------ 297 | 298 | This is a perfectly normal ELF string table, with a first entry which is simply 299 | \0 (so unnamed items can be denoted by the integer 0): it is specific to the CTF 300 | contianer alone. String table references in CTF have an MSB which, when 1 301 | (CTF_STRTAB_1), means to use a specific ELF string table (usually the one 302 | accompanying the symbol table used for the function info and data object 303 | sections). 304 | -------------------------------------------------------------------------------- /include/Build: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. 2 | # 3 | # Licensed under the Universal Permissive License v 1.0 as shown at 4 | # http://oss.oracle.com/licenses/upl. 5 | # 6 | # Licensed under the GNU General Public License (GPL), version 2. 7 | 8 | include_DIR := $(current-dir) 9 | 10 | HEADERS_INSTALL := sys/ctf.h \ 11 | sys/ctf_types.h 12 | 13 | # This project is also included in dtrace as a submodule, to assist in 14 | # test coverage analysis and debugging as part of dtrace. We don't want 15 | # to install it in that situation. 16 | ifeq ($(PROJECT),libdtrace-ctf) 17 | install:: 18 | mkdir -p $(INCLUDEDIR)/sys 19 | $(call describe-install-target,$(INCLUDEDIR)/sys,$(notdir $(HEADERS_INSTALL)) ctf-api.h) 20 | cd $(include_DIR) && install -m 644 $(HEADERS_INSTALL) $(INCLUDEDIR)/sys 21 | cd $(include_DIR) && install -m 644 sys/ctf-api.h $(INCLUDEDIR)/sys/ctf_api.h 22 | endif 23 | -------------------------------------------------------------------------------- /include/GNUmakefile: -------------------------------------------------------------------------------- 1 | %: 2 | $(MAKE) -C .. $@ 3 | 4 | all:: 5 | $(MAKE) -C .. all 6 | -------------------------------------------------------------------------------- /include/sys/ctf-api.h: -------------------------------------------------------------------------------- 1 | /* Public API to libctf. 2 | Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. 3 | 4 | Licensed under the Universal Permissive License v 1.0 as shown at 5 | http://oss.oracle.com/licenses/upl. 6 | 7 | Licensed under the GNU General Public License (GPL), version 2. */ 8 | 9 | /* This header file defines the interfaces available from the CTF debugger 10 | library, libctf. This API can be used by a debugger to operate on data in 11 | the Compact ANSI-C Type Format (CTF). */ 12 | 13 | #ifndef _CTF_API_H 14 | #define _CTF_API_H 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #ifdef __cplusplus 21 | extern "C" 22 | { 23 | #endif 24 | 25 | /* Clients can open one or more CTF containers and obtain a pointer to an 26 | opaque ctf_file_t. Types are identified by an opaque ctf_id_t token. 27 | They can also open or create read-only archives of CTF containers in a 28 | ctf_archive_t. 29 | 30 | These opaque definitions allow libctf to evolve without breaking clients. */ 31 | 32 | typedef struct ctf_file ctf_file_t; 33 | typedef struct ctf_archive_internal ctf_archive_t; 34 | typedef unsigned long ctf_id_t; 35 | 36 | /* This opaque definition allows libctf to accept BFD data structures without 37 | importing all the BFD noise into users' namespaces. */ 38 | 39 | struct bfd; 40 | 41 | /* If the debugger needs to provide the CTF library with a set of raw buffers 42 | for use as the CTF data, symbol table, and string table, it can do so by 43 | filling in ctf_sect_t structures and passing them to ctf_bufopen(). 44 | 45 | The contents of this structure must always be in native endianness (no 46 | byteswapping is performed). */ 47 | 48 | typedef struct ctf_sect 49 | { 50 | const char *cts_name; /* Section name (if any). */ 51 | #ifndef BFD_ONLY 52 | unsigned long cts_type; /* Section type (ELF SHT_... value). */ 53 | unsigned long cts_flags; /* Section flags (ELF SHF_... value). */ 54 | #endif 55 | const void *cts_data; /* Pointer to section data. */ 56 | size_t cts_size; /* Size of data in bytes. */ 57 | size_t cts_entsize; /* Size of each section entry (symtab only). */ 58 | #ifndef BFD_ONLY 59 | off64_t cts_offset; /* File offset of this section (if any). */ 60 | #endif 61 | } ctf_sect_t; 62 | 63 | /* A minimal symbol extracted from a linker's internal symbol table 64 | representation. */ 65 | 66 | typedef struct ctf_link_sym 67 | { 68 | /* The st_name will not be accessed outside the call to 69 | ctf_link_shuffle_syms(). */ 70 | 71 | const char *st_name; 72 | uint32_t st_shndx; 73 | uint32_t st_type; 74 | uint32_t st_value; 75 | } ctf_link_sym_t; 76 | 77 | /* Indication of how to share types when linking. */ 78 | 79 | /* Share all types thare are not in conflict. The default. */ 80 | #define CTF_LINK_SHARE_UNCONFLICTED 0x0 81 | 82 | /* Share only types that are used by multiple inputs. Not implemented yet. */ 83 | #define CTF_LINK_SHARE_DUPLICATED 0x1 84 | 85 | /* Symbolic names for CTF sections. */ 86 | 87 | typedef enum ctf_sect_names 88 | { 89 | CTF_SECT_HEADER, 90 | CTF_SECT_LABEL, 91 | CTF_SECT_OBJT, 92 | CTF_SECT_FUNC, 93 | CTF_SECT_VAR, 94 | CTF_SECT_TYPE, 95 | CTF_SECT_STR 96 | } ctf_sect_names_t; 97 | 98 | /* Encoding information for integers, floating-point values, and certain other 99 | intrinsics can be obtained by calling ctf_type_encoding(), below. The flags 100 | field will contain values appropriate for the type defined in . */ 101 | 102 | typedef struct ctf_encoding 103 | { 104 | uint32_t cte_format; /* Data format (CTF_INT_* or CTF_FP_* flags). */ 105 | uint32_t cte_offset; /* Offset of value in bits. */ 106 | uint32_t cte_bits; /* Size of storage in bits. */ 107 | } ctf_encoding_t; 108 | 109 | typedef struct ctf_membinfo 110 | { 111 | ctf_id_t ctm_type; /* Type of struct or union member. */ 112 | unsigned long ctm_offset; /* Offset of member in bits. */ 113 | } ctf_membinfo_t; 114 | 115 | typedef struct ctf_arinfo 116 | { 117 | ctf_id_t ctr_contents; /* Type of array contents. */ 118 | ctf_id_t ctr_index; /* Type of array index. */ 119 | uint32_t ctr_nelems; /* Number of elements. */ 120 | } ctf_arinfo_t; 121 | 122 | typedef struct ctf_funcinfo 123 | { 124 | ctf_id_t ctc_return; /* Function return type. */ 125 | uint32_t ctc_argc; /* Number of typed arguments to function. */ 126 | uint32_t ctc_flags; /* Function attributes (see below). */ 127 | } ctf_funcinfo_t; 128 | 129 | typedef struct ctf_lblinfo 130 | { 131 | ctf_id_t ctb_type; /* Last type associated with the label. */ 132 | } ctf_lblinfo_t; 133 | 134 | typedef struct ctf_snapshot_id 135 | { 136 | unsigned long dtd_id; /* Highest DTD ID at time of snapshot. */ 137 | unsigned long snapshot_id; /* Snapshot id at time of snapshot. */ 138 | } ctf_snapshot_id_t; 139 | 140 | #define CTF_FUNC_VARARG 0x1 /* Function arguments end with varargs. */ 141 | 142 | /* Functions that return a ctf_id_t use the following value to indicate failure. 143 | ctf_errno() can be used to obtain an error code. Functions that return 144 | a straight integral -1 also use ctf_errno(). */ 145 | #define CTF_ERR ((ctf_id_t) -1L) 146 | 147 | #define ECTF_BASE 1000 /* Base value for libctf errnos. */ 148 | 149 | #ifndef BFD_ONLY 150 | /* Definitions to inform callers about silently changed semantics. */ 151 | #define LIBDTRACE_CTF_OMISSIBLE_CTF_UPDATE 1 152 | #endif 153 | 154 | enum 155 | { 156 | ECTF_FMT = ECTF_BASE, /* File is not in CTF or ELF format. */ 157 | ECTF_BFDERR, /* BFD error. */ 158 | ECTF_CTFVERS, /* CTF version is more recent than libctf. */ 159 | ECTF_BFD_AMBIGUOUS, /* Ambiguous BFD target. */ 160 | ECTF_SYMTAB, /* Symbol table uses invalid entry size. */ 161 | ECTF_SYMBAD, /* Symbol table data buffer invalid. */ 162 | ECTF_STRBAD, /* String table data buffer invalid. */ 163 | ECTF_CORRUPT, /* File data corruption detected. */ 164 | ECTF_NOCTFDATA, /* ELF file does not contain CTF data. */ 165 | ECTF_NOCTFBUF, /* Buffer does not contain CTF data. */ 166 | ECTF_NOSYMTAB, /* Symbol table data is not available. */ 167 | ECTF_NOPARENT, /* Parent CTF container is not available. */ 168 | ECTF_DMODEL, /* Data model mismatch. */ 169 | ECTF_LINKADDEDLATE, /* File added to link too late. */ 170 | ECTF_ZALLOC, /* Failed to allocate (de)compression buffer. */ 171 | ECTF_DECOMPRESS, /* Failed to decompress CTF data. */ 172 | ECTF_STRTAB, /* String table for this string is missing. */ 173 | ECTF_BADNAME, /* String offset is corrupt w.r.t. strtab. */ 174 | ECTF_BADID, /* Invalid type ID number. */ 175 | ECTF_NOTSOU, /* Type is not a struct or union. */ 176 | ECTF_NOTENUM, /* Type is not an enum. */ 177 | ECTF_NOTSUE, /* Type is not a struct, union, or enum. */ 178 | ECTF_NOTINTFP, /* Type is not an integer, float, or enum. */ 179 | ECTF_NOTARRAY, /* Type is not an array. */ 180 | ECTF_NOTREF, /* Type does not reference another type. */ 181 | ECTF_NAMELEN, /* Buffer is too small to hold type name. */ 182 | ECTF_NOTYPE, /* No type found corresponding to name. */ 183 | ECTF_SYNTAX, /* Syntax error in type name. */ 184 | ECTF_NOTFUNC, /* Symbol entry or type is not a function. */ 185 | ECTF_NOFUNCDAT, /* No func info available for function. */ 186 | ECTF_NOTDATA, /* Symtab entry does not refer to a data obj. */ 187 | ECTF_NOTYPEDAT, /* No type info available for object. */ 188 | ECTF_NOLABEL, /* No label found corresponding to name. */ 189 | ECTF_NOLABELDATA, /* File does not contain any labels. */ 190 | ECTF_NOTSUP, /* Feature not supported. */ 191 | ECTF_NOENUMNAM, /* Enum element name not found. */ 192 | ECTF_NOMEMBNAM, /* Member name not found. */ 193 | ECTF_RDONLY, /* CTF container is read-only. */ 194 | ECTF_DTFULL, /* CTF type is full (no more members allowed). */ 195 | ECTF_FULL, /* CTF container is full. */ 196 | ECTF_DUPLICATE, /* Duplicate member or variable name. */ 197 | ECTF_CONFLICT, /* Conflicting type definition present. */ 198 | ECTF_OVERROLLBACK, /* Attempt to roll back past a ctf_update. */ 199 | ECTF_COMPRESS, /* Failed to compress CTF data. */ 200 | ECTF_ARCREATE, /* Error creating CTF archive. */ 201 | ECTF_ARNNAME, /* Name not found in CTF archive. */ 202 | ECTF_SLICEOVERFLOW, /* Overflow of type bitness or offset in slice. */ 203 | ECTF_DUMPSECTUNKNOWN, /* Unknown section number in dump. */ 204 | ECTF_DUMPSECTCHANGED, /* Section changed in middle of dump. */ 205 | ECTF_NOTYET, /* Feature not yet implemented. */ 206 | ECTF_INTERNAL, /* Internal error in link. */ 207 | ECTF_NONREPRESENTABLE /* Type not representable in CTF. */ 208 | }; 209 | 210 | /* The CTF data model is inferred to be the caller's data model or the data 211 | model of the given object, unless ctf_setmodel() is explicitly called. */ 212 | #define CTF_MODEL_ILP32 1 /* Object data model is ILP32. */ 213 | #define CTF_MODEL_LP64 2 /* Object data model is LP64. */ 214 | #ifdef _LP64 215 | # define CTF_MODEL_NATIVE CTF_MODEL_LP64 216 | #else 217 | # define CTF_MODEL_NATIVE CTF_MODEL_ILP32 218 | #endif 219 | 220 | /* Dynamic CTF containers can be created using ctf_create(). The ctf_add_* 221 | routines can be used to add new definitions to the dynamic container. 222 | New types are labeled as root or non-root to determine whether they are 223 | visible at the top-level program scope when subsequently doing a lookup. */ 224 | 225 | #define CTF_ADD_NONROOT 0 /* Type only visible in nested scope. */ 226 | #define CTF_ADD_ROOT 1 /* Type visible at top-level scope. */ 227 | 228 | /* These typedefs are used to define the signature for callback functions 229 | that can be used with the iteration and visit functions below. */ 230 | 231 | typedef int ctf_visit_f (const char *name, ctf_id_t type, unsigned long offset, 232 | int depth, void *arg); 233 | typedef int ctf_member_f (const char *name, ctf_id_t membtype, 234 | unsigned long offset, void *arg); 235 | typedef int ctf_enum_f (const char *name, int val, void *arg); 236 | typedef int ctf_variable_f (const char *name, ctf_id_t type, void *arg); 237 | typedef int ctf_type_f (ctf_id_t type, void *arg); 238 | typedef int ctf_type_all_f (ctf_id_t type, int flag, void *arg); 239 | typedef int ctf_label_f (const char *name, const ctf_lblinfo_t *info, 240 | void *arg); 241 | typedef int ctf_archive_member_f (ctf_file_t *fp, const char *name, void *arg); 242 | typedef int ctf_archive_raw_member_f (const char *name, const void *content, 243 | size_t len, void *arg); 244 | typedef char *ctf_dump_decorate_f (ctf_sect_names_t sect, 245 | char *line, void *arg); 246 | 247 | typedef struct ctf_dump_state ctf_dump_state_t; 248 | 249 | /* Opening. These mostly return an abstraction over both CTF files and CTF 250 | archives: so they can be used to open both. CTF files will appear to be an 251 | archive with one member named '.ctf'. The low-level functions 252 | ctf_simple_open() and ctf_bufopen() return ctf_file_t's directly, and cannot 253 | be used on CTF archives. */ 254 | 255 | extern ctf_archive_t *ctf_bfdopen (struct bfd *, int *); 256 | extern ctf_archive_t *ctf_bfdopen_ctfsect (struct bfd *, const ctf_sect_t *, 257 | int *); 258 | extern ctf_archive_t *ctf_fdopen (int fd, const char *filename, 259 | const char *target, int *errp); 260 | extern ctf_archive_t *ctf_open (const char *filename, 261 | const char *target, int *errp); 262 | #ifdef BFD_ONLY 263 | extern void ctf_close (ctf_archive_t *); 264 | #else 265 | #ifdef CTF_CLOSE_NEW_API 266 | extern void ctf_close (ctf_archive_t *); 267 | #else 268 | extern void ctf_close (ctf_file_t *); 269 | #endif 270 | #endif 271 | extern ctf_sect_t ctf_getdatasect (const ctf_file_t *); 272 | extern ctf_archive_t *ctf_get_arc (const ctf_file_t *); 273 | extern ctf_archive_t *ctf_arc_open (const char *, int *); 274 | extern ctf_archive_t *ctf_arc_bufopen (const ctf_sect_t *, 275 | const ctf_sect_t *, 276 | const ctf_sect_t *, 277 | int *); 278 | extern void ctf_arc_close (ctf_archive_t *); 279 | extern ctf_file_t *ctf_arc_open_by_name (const ctf_archive_t *, 280 | const char *, int *); 281 | extern ctf_file_t *ctf_arc_open_by_name_sections (const ctf_archive_t *, 282 | const ctf_sect_t *, 283 | const ctf_sect_t *, 284 | const char *, int *); 285 | 286 | /* The next functions return or close real CTF files, or write out CTF archives, 287 | not opaque containers around either. */ 288 | 289 | extern ctf_file_t *ctf_simple_open (const char *, size_t, const char *, size_t, 290 | size_t, const char *, size_t, int *); 291 | extern ctf_file_t *ctf_bufopen (const ctf_sect_t *, const ctf_sect_t *, 292 | const ctf_sect_t *, int *); 293 | extern void ctf_file_close (ctf_file_t *); 294 | 295 | extern int ctf_arc_write (const char *, ctf_file_t **, size_t, 296 | const char **, size_t); 297 | extern int ctf_arc_write_fd (int, ctf_file_t **, size_t, const char **, 298 | size_t); 299 | 300 | extern const char *ctf_cuname (ctf_file_t *); 301 | extern int ctf_cuname_set (ctf_file_t *, const char *); 302 | extern ctf_file_t *ctf_parent_file (ctf_file_t *); 303 | extern const char *ctf_parent_name (ctf_file_t *); 304 | extern int ctf_parent_name_set (ctf_file_t *, const char *); 305 | extern int ctf_type_isparent (ctf_file_t *, ctf_id_t); 306 | extern int ctf_type_ischild (ctf_file_t *, ctf_id_t); 307 | 308 | extern int ctf_import (ctf_file_t *, ctf_file_t *); 309 | extern int ctf_setmodel (ctf_file_t *, int); 310 | extern int ctf_getmodel (ctf_file_t *); 311 | 312 | extern void ctf_setspecific (ctf_file_t *, void *); 313 | extern void *ctf_getspecific (ctf_file_t *); 314 | 315 | extern int ctf_errno (ctf_file_t *); 316 | extern const char *ctf_errmsg (int); 317 | extern int ctf_version (int); 318 | 319 | extern int ctf_func_info (ctf_file_t *, unsigned long, ctf_funcinfo_t *); 320 | extern int ctf_func_args (ctf_file_t *, unsigned long, uint32_t, ctf_id_t *); 321 | extern int ctf_func_type_info (ctf_file_t *, ctf_id_t, ctf_funcinfo_t *); 322 | extern int ctf_func_type_args (ctf_file_t *, ctf_id_t, uint32_t, ctf_id_t *); 323 | 324 | extern ctf_id_t ctf_lookup_by_name (ctf_file_t *, const char *); 325 | extern ctf_id_t ctf_lookup_by_symbol (ctf_file_t *, unsigned long); 326 | extern ctf_id_t ctf_lookup_variable (ctf_file_t *, const char *); 327 | 328 | extern ctf_id_t ctf_type_resolve (ctf_file_t *, ctf_id_t); 329 | extern char *ctf_type_aname (ctf_file_t *, ctf_id_t); 330 | extern char *ctf_type_aname_raw (ctf_file_t *, ctf_id_t); 331 | extern ssize_t ctf_type_lname (ctf_file_t *, ctf_id_t, char *, size_t); 332 | extern char *ctf_type_name (ctf_file_t *, ctf_id_t, char *, size_t); 333 | extern ssize_t ctf_type_size (ctf_file_t *, ctf_id_t); 334 | extern ssize_t ctf_type_align (ctf_file_t *, ctf_id_t); 335 | extern int ctf_type_kind (ctf_file_t *, ctf_id_t); 336 | extern ctf_id_t ctf_type_reference (ctf_file_t *, ctf_id_t); 337 | extern ctf_id_t ctf_type_pointer (ctf_file_t *, ctf_id_t); 338 | extern int ctf_type_encoding (ctf_file_t *, ctf_id_t, ctf_encoding_t *); 339 | extern int ctf_type_visit (ctf_file_t *, ctf_id_t, ctf_visit_f *, void *); 340 | extern int ctf_type_cmp (ctf_file_t *, ctf_id_t, ctf_file_t *, ctf_id_t); 341 | extern int ctf_type_compat (ctf_file_t *, ctf_id_t, ctf_file_t *, ctf_id_t); 342 | 343 | extern int ctf_member_info (ctf_file_t *, ctf_id_t, const char *, 344 | ctf_membinfo_t *); 345 | extern int ctf_array_info (ctf_file_t *, ctf_id_t, ctf_arinfo_t *); 346 | 347 | extern const char *ctf_enum_name (ctf_file_t *, ctf_id_t, int); 348 | extern int ctf_enum_value (ctf_file_t *, ctf_id_t, const char *, int *); 349 | 350 | extern void ctf_label_set (ctf_file_t *, const char *); 351 | extern const char *ctf_label_get (ctf_file_t *); 352 | 353 | extern const char *ctf_label_topmost (ctf_file_t *); 354 | extern int ctf_label_info (ctf_file_t *, const char *, ctf_lblinfo_t *); 355 | 356 | extern int ctf_member_iter (ctf_file_t *, ctf_id_t, ctf_member_f *, void *); 357 | extern int ctf_enum_iter (ctf_file_t *, ctf_id_t, ctf_enum_f *, void *); 358 | extern int ctf_type_iter (ctf_file_t *, ctf_type_f *, void *); 359 | extern int ctf_type_iter_all (ctf_file_t *, ctf_type_all_f *, void *); 360 | extern int ctf_label_iter (ctf_file_t *, ctf_label_f *, void *); 361 | extern int ctf_variable_iter (ctf_file_t *, ctf_variable_f *, void *); 362 | extern int ctf_archive_iter (const ctf_archive_t *, ctf_archive_member_f *, 363 | void *); 364 | /* This function alone does not currently operate on CTF files masquerading 365 | as archives, and returns -EINVAL: the raw data is no longer available. It is 366 | expected to be used only by archiving tools, in any case, which have no need 367 | to deal with non-archives at all. */ 368 | extern int ctf_archive_raw_iter (const ctf_archive_t *, 369 | ctf_archive_raw_member_f *, void *); 370 | extern char *ctf_dump (ctf_file_t *, ctf_dump_state_t **state, 371 | ctf_sect_names_t sect, ctf_dump_decorate_f *, 372 | void *arg); 373 | 374 | extern ctf_id_t ctf_add_array (ctf_file_t *, uint32_t, 375 | const ctf_arinfo_t *); 376 | extern ctf_id_t ctf_add_const (ctf_file_t *, uint32_t, ctf_id_t); 377 | extern ctf_id_t ctf_add_enum_encoded (ctf_file_t *, uint32_t, const char *, 378 | const ctf_encoding_t *); 379 | extern ctf_id_t ctf_add_enum (ctf_file_t *, uint32_t, const char *); 380 | extern ctf_id_t ctf_add_float (ctf_file_t *, uint32_t, 381 | const char *, const ctf_encoding_t *); 382 | extern ctf_id_t ctf_add_forward (ctf_file_t *, uint32_t, const char *, 383 | uint32_t); 384 | extern ctf_id_t ctf_add_function (ctf_file_t *, uint32_t, 385 | const ctf_funcinfo_t *, const ctf_id_t *); 386 | extern ctf_id_t ctf_add_integer (ctf_file_t *, uint32_t, const char *, 387 | const ctf_encoding_t *); 388 | extern ctf_id_t ctf_add_slice (ctf_file_t *, uint32_t, ctf_id_t, const ctf_encoding_t *); 389 | extern ctf_id_t ctf_add_pointer (ctf_file_t *, uint32_t, ctf_id_t); 390 | extern ctf_id_t ctf_add_type (ctf_file_t *, ctf_file_t *, ctf_id_t); 391 | extern ctf_id_t ctf_add_typedef (ctf_file_t *, uint32_t, const char *, 392 | ctf_id_t); 393 | extern ctf_id_t ctf_add_restrict (ctf_file_t *, uint32_t, ctf_id_t); 394 | extern ctf_id_t ctf_add_struct (ctf_file_t *, uint32_t, const char *); 395 | extern ctf_id_t ctf_add_union (ctf_file_t *, uint32_t, const char *); 396 | extern ctf_id_t ctf_add_struct_sized (ctf_file_t *, uint32_t, const char *, 397 | size_t); 398 | extern ctf_id_t ctf_add_union_sized (ctf_file_t *, uint32_t, const char *, 399 | size_t); 400 | extern ctf_id_t ctf_add_volatile (ctf_file_t *, uint32_t, ctf_id_t); 401 | 402 | extern int ctf_add_enumerator (ctf_file_t *, ctf_id_t, const char *, int); 403 | extern int ctf_add_member (ctf_file_t *, ctf_id_t, const char *, ctf_id_t); 404 | extern int ctf_add_member_offset (ctf_file_t *, ctf_id_t, const char *, 405 | ctf_id_t, unsigned long); 406 | extern int ctf_add_member_encoded (ctf_file_t *, ctf_id_t, const char *, 407 | ctf_id_t, unsigned long, 408 | const ctf_encoding_t); 409 | 410 | extern int ctf_add_variable (ctf_file_t *, const char *, ctf_id_t); 411 | 412 | extern int ctf_set_array (ctf_file_t *, ctf_id_t, const ctf_arinfo_t *); 413 | 414 | extern ctf_file_t *ctf_create (int *); 415 | extern int ctf_update (ctf_file_t *); 416 | extern ctf_snapshot_id_t ctf_snapshot (ctf_file_t *); 417 | extern int ctf_rollback (ctf_file_t *, ctf_snapshot_id_t); 418 | extern int ctf_discard (ctf_file_t *); 419 | extern int ctf_write (ctf_file_t *, int); 420 | extern int ctf_gzwrite (ctf_file_t *fp, gzFile fd); 421 | extern int ctf_compress_write (ctf_file_t * fp, int fd); 422 | extern unsigned char *ctf_write_mem (ctf_file_t *, size_t *, size_t threshold); 423 | 424 | /* The ctf_link interfaces are not stable yet. No guarantees! */ 425 | 426 | extern int ctf_link_add_ctf (ctf_file_t *, ctf_archive_t *, const char *); 427 | extern int ctf_link (ctf_file_t *, int share_mode); 428 | typedef const char *ctf_link_strtab_string_f (uint32_t *offset, void *arg); 429 | extern int ctf_link_add_strtab (ctf_file_t *, ctf_link_strtab_string_f *, 430 | void *); 431 | typedef ctf_link_sym_t *ctf_link_iter_symbol_f (ctf_link_sym_t *dest, 432 | void *arg); 433 | extern int ctf_link_shuffle_syms (ctf_file_t *, ctf_link_iter_symbol_f *, 434 | void *); 435 | extern unsigned char *ctf_link_write (ctf_file_t *, size_t *size, 436 | size_t threshold); 437 | 438 | /* Specialist linker functions. These functions are not used by ld, but can be 439 | used by other prgorams making use of the linker machinery for other purposes 440 | to customize its output. */ 441 | extern int ctf_link_add_cu_mapping (ctf_file_t *, const char *from, 442 | const char *to); 443 | typedef char *ctf_link_memb_name_changer_f (ctf_file_t *, 444 | const char *, void *); 445 | extern void ctf_link_set_memb_name_changer 446 | (ctf_file_t *, ctf_link_memb_name_changer_f *, void *); 447 | 448 | extern void ctf_setdebug (int debug); 449 | extern int ctf_getdebug (void); 450 | 451 | #ifdef __cplusplus 452 | } 453 | #endif 454 | 455 | #endif /* _CTF_API_H */ 456 | -------------------------------------------------------------------------------- /include/sys/ctf_types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * Licensed under the Universal Permissive License v 1.0 as shown at 5 | * http://oss.oracle.com/licenses/upl. 6 | * 7 | * Licensed under the GNU General Public License (GPL), version 2. 8 | */ 9 | 10 | #ifndef CTF_SYS_TYPES_H 11 | #define CTF_SYS_TYPES_H 12 | 13 | #include 14 | 15 | /* 16 | * POSIX Extensions 17 | */ 18 | typedef unsigned char uchar_t; 19 | typedef unsigned short ushort_t; 20 | typedef unsigned int uint_t; 21 | typedef unsigned long ulong_t; 22 | 23 | /* 24 | * return x rounded up to an alignment boundary 25 | * eg, P2ROUNDUP(0x1234, 0x100) == 0x1300 (0x13*align) 26 | * eg, P2ROUNDUP(0x5600, 0x100) == 0x5600 (0x56*align) 27 | */ 28 | #define P2ROUNDUP(x, align) (-(-(x) & -(align))) 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /libctf/Build: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. 2 | # 3 | # Licensed under the Universal Permissive License v 1.0 as shown at 4 | # http://oss.oracle.com/licenses/upl. 5 | # 6 | # Licensed under the GNU General Public License (GPL), version 2. See the file 7 | # COPYING in the top level of this tree. 8 | 9 | BUILDLIBS += libdtrace-ctf 10 | SHLIBS += libdtrace-ctf 11 | libdtrace-ctf_CPPFLAGS = -I$(libdtrace-ctf_DIR) $(shell pkg-config --cflags glib-2.0) 12 | libdtrace-ctf_TARGET = libdtrace-ctf 13 | libdtrace-ctf_DIR := $(current-dir) 14 | libdtrace-ctf_SOURCES = ctf-open.c ctf-open-bfd.c ctf-archive.c ctf-create.c \ 15 | ctf-error.c ctf-hash.c ctf-labels.c ctf-link.c \ 16 | ctf-lookup.c ctf-decl.c ctf-types.c ctf-dump.c \ 17 | ctf-string.c ctf-subr.c ctf-util.c bsearch_r.c 18 | libdtrace-ctf_LIBS := $(shell pkg-config --libs glib-2.0) -lbfd -lz 19 | libdtrace-ctf_VERSION := 1.6.0 20 | libdtrace-ctf_SONAME := libdtrace-ctf.so.1 21 | libdtrace-ctf_VERSCRIPT := $(libdtrace-ctf_DIR)libdtrace-ctf.ver 22 | libdtrace-ctf_LIBSOURCES := libdtrace-ctf 23 | 24 | # This project is also included in dtrace as a submodule, to assist in 25 | # test coverage analysis and debugging as part of dtrace. We don't want 26 | # to install it in that situation. 27 | ifeq ($(PROJECT),libdtrace-ctf) 28 | install:: 29 | mkdir -p $(LIBDIR) 30 | $(call describe-install-target,$(LIBDIR),$(libdtrace-ctf_TARGET).so.$(libdtrace-ctf_VERSION)) 31 | install -m 755 $(objdir)/$(libdtrace-ctf_TARGET).so.$(libdtrace-ctf_VERSION) $(LIBDIR) 32 | $(call describe-install-target,$(LIBDIR),$(libdtrace-ctf_SONAME)) 33 | ln -sf libdtrace-ctf.so.$(libdtrace-ctf_VERSION) $(LIBDIR)/$(libdtrace-ctf_SONAME) 34 | $(call describe-install-target,$(LIBDIR),$(libdtrace-ctf_TARGET).so) 35 | ln -sf libdtrace-ctf.so.$(libdtrace-ctf_VERSION) $(LIBDIR)/$(libdtrace-ctf_TARGET).so 36 | endif 37 | -------------------------------------------------------------------------------- /libctf/GNUmakefile: -------------------------------------------------------------------------------- 1 | %: 2 | $(MAKE) -C .. $@ 3 | 4 | all:: 5 | $(MAKE) -C .. all 6 | -------------------------------------------------------------------------------- /libctf/bsearch_r.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1990 Regents of the University of California. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. [rescinded 22 July 1999] 14 | * 4. Neither the name of the University nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 | * SUCH DAMAGE. 29 | * 30 | * Not synced with GNU. 31 | */ 32 | 33 | #include "config.h" 34 | #include /* size_t */ 35 | #include 36 | 37 | /* 38 | * Perform a binary search. 39 | * 40 | * The code below is a bit sneaky. After a comparison fails, we 41 | * divide the work in half by moving either left or right. If lim 42 | * is odd, moving left simply involves halving lim: e.g., when lim 43 | * is 5 we look at item 2, so we change lim to 2 so that we will 44 | * look at items 0 & 1. If lim is even, the same applies. If lim 45 | * is odd, moving right again involes halving lim, this time moving 46 | * the base up one item past p: e.g., when lim is 5 we change base 47 | * to item 3 and make lim 2 so that we will look at items 3 and 4. 48 | * If lim is even, however, we have to shrink it by one before 49 | * halving: e.g., when lim is 4, we still looked at item 2, so we 50 | * have to make lim 3, then halve, obtaining 1, so that we will only 51 | * look at item 3. 52 | */ 53 | void * 54 | bsearch_r (register const void *key, const void *base0, 55 | size_t nmemb, register size_t size, 56 | register int (*compar)(const void *, const void *, void *), 57 | void *arg) 58 | { 59 | register const char *base = (const char *) base0; 60 | register int lim, cmp; 61 | register const void *p; 62 | 63 | for (lim = nmemb; lim != 0; lim >>= 1) { 64 | p = base + (lim >> 1) * size; 65 | cmp = (*compar)(key, p, arg); 66 | if (cmp == 0) 67 | return (void *)p; 68 | if (cmp > 0) { /* key > p: move right */ 69 | base = (const char *)p + size; 70 | lim--; 71 | } /* else move left */ 72 | } 73 | return (NULL); 74 | } 75 | -------------------------------------------------------------------------------- /libctf/ctf-decl.c: -------------------------------------------------------------------------------- 1 | /* C declarator syntax glue. 2 | Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. 3 | 4 | Licensed under the Universal Permissive License v 1.0 as shown at 5 | http://oss.oracle.com/licenses/upl. 6 | 7 | Licensed under the GNU General Public License (GPL), version 2. See the file 8 | COPYING in the top level of this tree. */ 9 | 10 | /* CTF Declaration Stack 11 | 12 | In order to implement ctf_type_name(), we must convert a type graph back 13 | into a C type declaration. Unfortunately, a type graph represents a storage 14 | class ordering of the type whereas a type declaration must obey the C rules 15 | for operator precedence, and the two orderings are frequently in conflict. 16 | For example, consider these CTF type graphs and their C declarations: 17 | 18 | CTF_K_POINTER -> CTF_K_FUNCTION -> CTF_K_INTEGER : int (*)() 19 | CTF_K_POINTER -> CTF_K_ARRAY -> CTF_K_INTEGER : int (*)[] 20 | 21 | In each case, parentheses are used to raise operator * to higher lexical 22 | precedence, so the string form of the C declaration cannot be constructed by 23 | walking the type graph links and forming the string from left to right. 24 | 25 | The functions in this file build a set of stacks from the type graph nodes 26 | corresponding to the C operator precedence levels in the appropriate order. 27 | The code in ctf_type_name() can then iterate over the levels and nodes in 28 | lexical precedence order and construct the final C declaration string. */ 29 | 30 | #include 31 | #include 32 | 33 | void 34 | ctf_decl_init (ctf_decl_t *cd) 35 | { 36 | int i; 37 | 38 | memset (cd, 0, sizeof (ctf_decl_t)); 39 | 40 | for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++) 41 | cd->cd_order[i] = CTF_PREC_BASE - 1; 42 | 43 | cd->cd_qualp = CTF_PREC_BASE; 44 | cd->cd_ordp = CTF_PREC_BASE; 45 | } 46 | 47 | void 48 | ctf_decl_fini (ctf_decl_t *cd) 49 | { 50 | ctf_decl_node_t *cdp, *ndp; 51 | int i; 52 | 53 | for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++) 54 | { 55 | for (cdp = ctf_list_next (&cd->cd_nodes[i]); cdp != NULL; cdp = ndp) 56 | { 57 | ndp = ctf_list_next (cdp); 58 | free (cdp); 59 | } 60 | } 61 | } 62 | 63 | void 64 | ctf_decl_push (ctf_decl_t *cd, ctf_file_t *fp, ctf_id_t type) 65 | { 66 | ctf_decl_node_t *cdp; 67 | ctf_decl_prec_t prec; 68 | uint32_t kind, n = 1; 69 | int is_qual = 0; 70 | 71 | const ctf_type_t *tp; 72 | ctf_arinfo_t ar; 73 | 74 | if ((tp = ctf_lookup_by_id (&fp, type)) == NULL) 75 | { 76 | cd->cd_err = fp->ctf_errno; 77 | return; 78 | } 79 | 80 | switch (kind = LCTF_INFO_KIND (fp, tp->ctt_info)) 81 | { 82 | case CTF_K_ARRAY: 83 | (void) ctf_array_info (fp, type, &ar); 84 | ctf_decl_push (cd, fp, ar.ctr_contents); 85 | n = ar.ctr_nelems; 86 | prec = CTF_PREC_ARRAY; 87 | break; 88 | 89 | case CTF_K_TYPEDEF: 90 | if (ctf_strptr (fp, tp->ctt_name)[0] == '\0') 91 | { 92 | ctf_decl_push (cd, fp, tp->ctt_type); 93 | return; 94 | } 95 | prec = CTF_PREC_BASE; 96 | break; 97 | 98 | case CTF_K_FUNCTION: 99 | ctf_decl_push (cd, fp, tp->ctt_type); 100 | prec = CTF_PREC_FUNCTION; 101 | break; 102 | 103 | case CTF_K_POINTER: 104 | ctf_decl_push (cd, fp, tp->ctt_type); 105 | prec = CTF_PREC_POINTER; 106 | break; 107 | 108 | case CTF_K_SLICE: 109 | ctf_decl_push (cd, fp, ctf_type_reference (fp, type)); 110 | prec = CTF_PREC_BASE; 111 | break; 112 | 113 | case CTF_K_VOLATILE: 114 | case CTF_K_CONST: 115 | case CTF_K_RESTRICT: 116 | ctf_decl_push (cd, fp, tp->ctt_type); 117 | prec = cd->cd_qualp; 118 | is_qual++; 119 | break; 120 | 121 | default: 122 | prec = CTF_PREC_BASE; 123 | } 124 | 125 | if ((cdp = malloc (sizeof (ctf_decl_node_t))) == NULL) 126 | { 127 | cd->cd_err = EAGAIN; 128 | return; 129 | } 130 | 131 | cdp->cd_type = type; 132 | cdp->cd_kind = kind; 133 | cdp->cd_n = n; 134 | 135 | if (ctf_list_next (&cd->cd_nodes[prec]) == NULL) 136 | cd->cd_order[prec] = cd->cd_ordp++; 137 | 138 | /* Reset cd_qualp to the highest precedence level that we've seen so 139 | far that can be qualified (CTF_PREC_BASE or CTF_PREC_POINTER). */ 140 | 141 | if (prec > cd->cd_qualp && prec < CTF_PREC_ARRAY) 142 | cd->cd_qualp = prec; 143 | 144 | /* C array declarators are ordered inside out so prepend them. Also by 145 | convention qualifiers of base types precede the type specifier (e.g. 146 | const int vs. int const) even though the two forms are equivalent. */ 147 | 148 | if (kind == CTF_K_ARRAY || (is_qual && prec == CTF_PREC_BASE)) 149 | ctf_list_prepend (&cd->cd_nodes[prec], cdp); 150 | else 151 | ctf_list_append (&cd->cd_nodes[prec], cdp); 152 | } 153 | 154 | _libctf_printflike_ (2, 3) 155 | void ctf_decl_sprintf (ctf_decl_t *cd, const char *format, ...) 156 | { 157 | va_list ap; 158 | char *str; 159 | int n; 160 | 161 | if (cd->cd_enomem) 162 | return; 163 | 164 | va_start (ap, format); 165 | n = vasprintf (&str, format, ap); 166 | va_end (ap); 167 | 168 | if (n > 0) 169 | { 170 | char *newbuf; 171 | if ((newbuf = ctf_str_append (cd->cd_buf, str)) != NULL) 172 | cd->cd_buf = newbuf; 173 | } 174 | 175 | /* Sticky error condition. */ 176 | if (n < 0 || cd->cd_buf == NULL) 177 | { 178 | free (cd->cd_buf); 179 | cd->cd_buf = NULL; 180 | cd->cd_enomem = 1; 181 | } 182 | 183 | free (str); 184 | } 185 | 186 | char *ctf_decl_buf (ctf_decl_t *cd) 187 | { 188 | return cd->cd_buf; 189 | } 190 | -------------------------------------------------------------------------------- /libctf/ctf-decls.h: -------------------------------------------------------------------------------- 1 | /* Escape hatch for autoconfiscated declarations. 2 | Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 3 | 4 | Licensed under the Universal Permissive License v 1.0 as shown at 5 | http://oss.oracle.com/licenses/upl. 6 | 7 | Licensed under the GNU General Public License (GPL), version 2. See the file 8 | COPYING in the top level of this tree. 9 | 10 | Not synced with GNU. */ 11 | 12 | #ifndef _CTF_DECLS_H 13 | #define _CTF_DECLS_H 14 | 15 | #include "config.h" 16 | #include 17 | 18 | #define ctf_qsort_r(base, nmemb, size, compar, arg) \ 19 | qsort_r ((base), (nmemb), (size), (compar), (arg)) 20 | 21 | #ifndef HAVE_BSEARCH_R 22 | extern void * 23 | bsearch_r (register const void *key, const void *base0, 24 | size_t nmemb, register size_t size, 25 | register int (*compar)(const void *, const void *, void *), 26 | void *arg); 27 | #endif 28 | 29 | #define xstrdup(str) strdup (str) 30 | #define xstrndup(str, n) strndup (str, n) 31 | 32 | /* Work around recent changes in binutils APIs. 33 | 34 | Since most of them are macros, we have to outright redeclare them, since we 35 | can't wrap them. */ 36 | 37 | #ifndef HAVE_ONE_ARG_BFD_SECTION_SIZE 38 | #include 39 | #undef bfd_section_size 40 | #define bfd_section_size(ptr) ((ptr)->size) 41 | #endif 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /libctf/ctf-endian.h: -------------------------------------------------------------------------------- 1 | /* Endianness-swapping wrapper. 2 | Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved. 3 | 4 | Licensed under the Universal Permissive License v 1.0 as shown at 5 | http://oss.oracle.com/licenses/upl. 6 | 7 | Licensed under the GNU General Public License (GPL), version 2. See the file 8 | COPYING in the top level of this tree. 9 | 10 | Not synced with GNU. */ 11 | 12 | #ifndef _CTF_ENDIAN_H 13 | #define _CTF_ENDIAN_H 14 | 15 | #include "config.h" 16 | #include 17 | 18 | #ifdef HAVE_ENDIAN_H 19 | #include 20 | #else 21 | #error is required. 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /libctf/ctf-error.c: -------------------------------------------------------------------------------- 1 | /* Error table. 2 | Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. 3 | 4 | Licensed under the Universal Permissive License v 1.0 as shown at 5 | http://oss.oracle.com/licenses/upl. 6 | 7 | Licensed under the GNU General Public License (GPL), version 2. See the file 8 | COPYING in the top level of this tree. */ 9 | 10 | #include 11 | 12 | static const char *const _ctf_errlist[] = { 13 | "File is not in CTF or ELF format", /* ECTF_FMT */ 14 | "BFD error", /* ECTF_BFDERR */ 15 | "File uses more recent CTF version than libctf", /* ECTF_CTFVERS */ 16 | "Ambiguous BFD target", /* ECTF_BFD_AMBIGUOUS */ 17 | "Symbol table uses invalid entry size", /* ECTF_SYMTAB */ 18 | "Symbol table data buffer is not valid", /* ECTF_SYMBAD */ 19 | "String table data buffer is not valid", /* ECTF_STRBAD */ 20 | "File data structure corruption detected", /* ECTF_CORRUPT */ 21 | "File does not contain CTF data", /* ECTF_NOCTFDATA */ 22 | "Buffer does not contain CTF data", /* ECTF_NOCTFBUF */ 23 | "Symbol table information is not available", /* ECTF_NOSYMTAB */ 24 | "Type information is in parent and unavailable", /* ECTF_NOPARENT */ 25 | "Cannot import types with different data model", /* ECTF_DMODEL */ 26 | "File added to link too late", /* ECTF_LINKADDEDLATE */ 27 | "Failed to allocate (de)compression buffer", /* ECTF_ZALLOC */ 28 | "Failed to decompress CTF data", /* ECTF_DECOMPRESS */ 29 | "External string table is not available", /* ECTF_STRTAB */ 30 | "String name offset is corrupt", /* ECTF_BADNAME */ 31 | "Invalid type identifier", /* ECTF_BADID */ 32 | "Type is not a struct or union", /* ECTF_NOTSOU */ 33 | "Type is not an enum", /* ECTF_NOTENUM */ 34 | "Type is not a struct, union, or enum", /* ECTF_NOTSUE */ 35 | "Type is not an integer, float, or enum", /* ECTF_NOTINTFP */ 36 | "Type is not an array", /* ECTF_NOTARRAY */ 37 | "Type does not reference another type", /* ECTF_NOTREF */ 38 | "Input buffer is too small for type name", /* ECTF_NAMELEN */ 39 | "No type information available for that name", /* ECTF_NOTYPE */ 40 | "Syntax error in type name", /* ECTF_SYNTAX */ 41 | "Symbol table entry or type is not a function", /* ECTF_NOTFUNC */ 42 | "No function information available for symbol", /* ECTF_NOFUNCDAT */ 43 | "Symbol table entry is not a data object", /* ECTF_NOTDATA */ 44 | "No type information available for symbol", /* ECTF_NOTYPEDAT */ 45 | "No label information available for that name", /* ECTF_NOLABEL */ 46 | "File does not contain any labels", /* ECTF_NOLABELDATA */ 47 | "Feature not supported", /* ECTF_NOTSUP */ 48 | "Invalid enum element name", /* ECTF_NOENUMNAM */ 49 | "Invalid member name", /* ECTF_NOMEMBNAM */ 50 | "CTF container is read-only", /* ECTF_RDONLY */ 51 | "Limit on number of dynamic type members reached", /* ECTF_DTFULL */ 52 | "Limit on number of dynamic types reached", /* ECTF_FULL */ 53 | "Duplicate member or variable name", /* ECTF_DUPLICATE */ 54 | "Conflicting type is already defined", /* ECTF_CONFLICT */ 55 | "Attempt to roll back past a ctf_update", /* ECTF_OVERROLLBACK */ 56 | "Failed to compress CTF data", /* ECTF_COMPRESS */ 57 | "Failed to create CTF archive", /* ECTF_ARCREATE */ 58 | "Name not found in CTF archive", /* ECTF_ARNNAME */ 59 | "Overflow of type bitness or offset in slice", /* ECTF_SLICEOVERFLOW */ 60 | "Unknown section number in dump", /* ECTF_DUMPSECTUNKNOWN */ 61 | "Section changed in middle of dump", /* ECTF_DUMPSECTCHANGED */ 62 | "Feature not yet implemented", /* ECTF_NOTYET */ 63 | "Internal error in link", /* ECTF_INTERNAL */ 64 | "Type not representable in CTF" /* ECTF_NONREPRESENTABLE */ 65 | }; 66 | 67 | static const int _ctf_nerr = sizeof (_ctf_errlist) / sizeof (_ctf_errlist[0]); 68 | 69 | const char * 70 | ctf_errmsg (int error) 71 | { 72 | const char *str; 73 | 74 | if (error >= ECTF_BASE && (error - ECTF_BASE) < _ctf_nerr) 75 | str = _ctf_errlist[error - ECTF_BASE]; 76 | else 77 | str = ctf_strerror (error); 78 | 79 | return (str ? str : "Unknown error"); 80 | } 81 | 82 | int 83 | ctf_errno (ctf_file_t * fp) 84 | { 85 | return fp->ctf_errno; 86 | } 87 | -------------------------------------------------------------------------------- /libctf/ctf-hash.c: -------------------------------------------------------------------------------- 1 | /* Interface to hashtable implementations. 2 | Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved. 3 | 4 | Licensed under the Universal Permissive License v 1.0 as shown at 5 | http://oss.oracle.com/licenses/upl. 6 | 7 | Licensed under the GNU General Public License (GPL), version 2. See the file 8 | COPYING in the top level of this tree. 9 | 10 | Not synced with GNU. */ 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | /* We have two hashtable implementations: one, ctf_dynhash_*(), is an interface to 17 | a dynamically-expanding hash with unknown size that should support addition 18 | of large numbers of items, and removal as well, and is used only at 19 | type-insertion time; the other, ctf_dynhash_*(), is an interface to a 20 | fixed-size hash from const char * -> ctf_id_t with number of elements 21 | specified at creation time, that should support addition of items but need 22 | not support removal. These can be implemented by the same underlying hashmap 23 | if you wish. */ 24 | 25 | /* ctf_dynhash is a purely-opaque type: it has no definition inside this file, 26 | where it is instead universally cast into the type of the *real* hash 27 | implementation. */ 28 | 29 | static const uint32_t _CTF_EMPTY[1] = { 0 }; 30 | 31 | /* Hash functions. */ 32 | 33 | unsigned int 34 | ctf_hash_integer (const void *ptr) 35 | { 36 | /* Avoid g_direct_hash() for now: see glib commit dc983d74cc608f. */ 37 | 38 | return GPOINTER_TO_UINT (ptr) * 11; 39 | } 40 | 41 | int 42 | ctf_hash_eq_integer (const void *a, const void *b) 43 | { 44 | return g_direct_equal (a, b); 45 | } 46 | 47 | unsigned int 48 | ctf_hash_string (const void *ptr) 49 | { 50 | return g_str_hash (ptr); 51 | } 52 | 53 | int 54 | ctf_hash_eq_string (const void *a, const void *b) 55 | { 56 | return g_str_equal (a, b); 57 | } 58 | 59 | /* Hash a type_mapping_key. */ 60 | unsigned int 61 | ctf_hash_type_mapping_key (const void *ptr) 62 | { 63 | ctf_link_type_mapping_key_t *k = (ctf_link_type_mapping_key_t *) ptr; 64 | return GPOINTER_TO_UINT (k->cltm_fp) * 11 65 | + 59 * GPOINTER_TO_UINT (k->cltm_idx) * 13; 66 | } 67 | 68 | int 69 | ctf_hash_eq_type_mapping_key (const void *a, const void *b) 70 | { 71 | ctf_link_type_mapping_key_t *key_a = (ctf_link_type_mapping_key_t *) a; 72 | ctf_link_type_mapping_key_t *key_b = (ctf_link_type_mapping_key_t *) b; 73 | 74 | return (key_a->cltm_fp == key_b->cltm_fp) 75 | && (key_a->cltm_idx == key_b->cltm_idx); 76 | } 77 | 78 | /* The dynhash, used for hashes whose size is not known at creation time. 79 | Implemented using GHashTable, an expanding hash. */ 80 | 81 | ctf_dynhash_t * 82 | ctf_dynhash_create (ctf_hash_fun hash_fun, ctf_hash_eq_fun eq_fun, 83 | ctf_hash_free_fun key_free, 84 | ctf_hash_free_fun value_free) 85 | { 86 | return (ctf_dynhash_t *) g_hash_table_new_full ((GHashFunc) hash_fun, 87 | (GEqualFunc) eq_fun, 88 | (GDestroyNotify) key_free, 89 | (GDestroyNotify) value_free); 90 | } 91 | 92 | int 93 | ctf_dynhash_insert (ctf_dynhash_t *hp, void *key, void *value) 94 | { 95 | g_hash_table_insert ((GHashTable *) hp, (gpointer) key, value); 96 | return 0; 97 | } 98 | 99 | void 100 | ctf_dynhash_remove (ctf_dynhash_t *hp, const void *key) 101 | { 102 | g_hash_table_remove ((GHashTable *) hp, key); 103 | } 104 | 105 | void 106 | ctf_dynhash_empty (ctf_dynhash_t *hp) 107 | { 108 | g_hash_table_remove_all ((GHashTable *) hp); 109 | } 110 | 111 | void * 112 | ctf_dynhash_lookup (ctf_dynhash_t *hp, const void *key) 113 | { 114 | return g_hash_table_lookup ((GHashTable *) hp, key); 115 | } 116 | 117 | void 118 | ctf_dynhash_iter (ctf_dynhash_t *hp, ctf_hash_iter_f fun, void *arg) 119 | { 120 | g_hash_table_foreach ((GHashTable *)hp, fun, arg); 121 | } 122 | 123 | void 124 | ctf_dynhash_iter_remove (ctf_dynhash_t *hp, ctf_hash_iter_remove_f fun, 125 | void *arg) 126 | { 127 | g_hash_table_foreach_remove ((GHashTable *)hp, fun, arg); 128 | } 129 | 130 | void 131 | ctf_dynhash_destroy (ctf_dynhash_t *hp) 132 | { 133 | if (hp != NULL) 134 | g_hash_table_destroy ((GHashTable *) hp); 135 | } 136 | 137 | /* ctf_hash, used for fixed-size maps from const char * -> ctf_id_t without 138 | removal. TODO: implement one-shot initialization with precomputed bucket 139 | distribution. */ 140 | 141 | typedef struct ctf_helem 142 | { 143 | uint32_t h_name; /* Reference to name in string table. */ 144 | uint32_t h_next; /* Index of next element in hash chain. */ 145 | ctf_id_t h_type; /* Corresponding type ID number. */ 146 | } ctf_helem_t; 147 | 148 | typedef struct ctf_fixed_hash 149 | { 150 | ctf_helem_t *h_chains; /* Hash chains buffer. */ 151 | uint32_t *h_buckets; /* Hash bucket array (chain indices). */ 152 | uint32_t h_nbuckets; /* Number of elements in bucket array. */ 153 | uint32_t h_nelems; /* Number of elements in hash table. */ 154 | uint32_t h_free; /* Index of next free hash element. */ 155 | } ctf_hash_t; 156 | 157 | /* Table of primes up to almost as high as it's worth going -- there is no point 158 | going all the way up to 2^32: an average chain length of four is not a 159 | disaster. */ 160 | 161 | static uint32_t const primes[] = { 1021, 2039, 4093, 8191, 16381, 162 | 32749, 65521, 131071, 262139, 163 | 524287, 1048573, 2097143, 164 | 4194301, 8388593, 16777213, 165 | 33554393, 67108859, 134217689, 166 | 268435399, 536870909, 1073741789 }; 167 | 168 | /* Find a prime greater than N, near a power of two. */ 169 | 170 | static uint32_t 171 | find_prime (unsigned long n) 172 | { 173 | uint32_t low = 0; 174 | uint32_t high = sizeof(primes) / sizeof(uint32_t); 175 | 176 | while (low != high) 177 | { 178 | uint32_t mid = low + (high - low) / 2; 179 | if (n > primes[mid]) 180 | low = mid + 1; 181 | else 182 | high = mid; 183 | } 184 | return primes[low]; 185 | } 186 | 187 | ctf_hash_t * 188 | ctf_hash_create (unsigned long nelems, ctf_hash_fun hash_fun, 189 | ctf_hash_eq_fun eq_fun) 190 | { 191 | ctf_hash_t *hp; 192 | 193 | if ((hash_fun != ctf_hash_string) || (eq_fun != ctf_hash_eq_string)) 194 | { 195 | errno = EINVAL; 196 | return NULL; 197 | } 198 | 199 | if (nelems > UINT32_MAX) 200 | { 201 | errno = EOVERFLOW; 202 | return NULL; 203 | } 204 | 205 | if ((hp = malloc (sizeof (ctf_hash_t))) == NULL) 206 | { 207 | errno = ENOMEM; 208 | return NULL; 209 | } 210 | 211 | /* If the hash table is going to be empty, don't bother allocating any 212 | memory and make the only bucket point to a zero so lookups fail. */ 213 | 214 | if (nelems == 0) 215 | { 216 | memset (hp, 0, sizeof (ctf_hash_t)); 217 | hp->h_buckets = (uint32_t *) _CTF_EMPTY; 218 | hp->h_nbuckets = 1; 219 | return hp; 220 | } 221 | 222 | hp->h_nbuckets = find_prime (nelems); 223 | hp->h_nelems = nelems + 1; /* We use index zero as a sentinel. */ 224 | hp->h_free = 1; /* First free element is index 1. */ 225 | 226 | hp->h_buckets = calloc (hp->h_nbuckets, sizeof (uint32_t)); 227 | hp->h_chains = calloc (hp->h_nelems, sizeof (ctf_helem_t)); 228 | 229 | if (hp->h_buckets == NULL || hp->h_chains == NULL) 230 | { 231 | ctf_hash_destroy (hp); 232 | errno = ENOMEM; 233 | return NULL; 234 | } 235 | 236 | return hp; 237 | } 238 | 239 | uint32_t 240 | ctf_hash_size (const ctf_hash_t *hp) 241 | { 242 | return (hp->h_nelems ? hp->h_nelems - 1 : 0); 243 | } 244 | 245 | int 246 | ctf_hash_insert_type (ctf_hash_t * hp, ctf_file_t * fp, uint32_t type, 247 | uint32_t name) 248 | { 249 | const char *str = ctf_strraw (fp, name); 250 | ctf_helem_t *hep = &hp->h_chains[hp->h_free]; 251 | uint32_t h; 252 | 253 | if (type == 0) 254 | return EINVAL; 255 | 256 | if (hp->h_free >= hp->h_nelems) 257 | return EOVERFLOW; 258 | 259 | if (str == NULL 260 | && CTF_NAME_STID (name) == CTF_STRTAB_1 261 | && fp->ctf_syn_ext_strtab == NULL 262 | && fp->ctf_str[CTF_NAME_STID (name)].cts_strs == NULL) 263 | return ECTF_STRTAB; 264 | 265 | if (str == NULL) 266 | return ECTF_BADNAME; 267 | 268 | if (str[0] == '\0') 269 | return 0; /* Just ignore empty strings on behalf of caller. */ 270 | 271 | hep->h_name = name; 272 | hep->h_type = type; 273 | h = ctf_hash_string (str) % hp->h_nbuckets; 274 | hep->h_next = hp->h_buckets[h]; 275 | hp->h_buckets[h] = hp->h_free++; 276 | 277 | return 0; 278 | } 279 | 280 | /* Wrapper for ctf_hash_lookup_type/ctf_hash_insert_type: if the key is already 281 | in the hash, override the previous definition with this new official 282 | definition. If the key is not present, then call ctf_hash_insert_type() and 283 | hash it in. */ 284 | int 285 | ctf_hash_define_type (ctf_hash_t *hp, ctf_file_t *fp, uint32_t type, 286 | uint32_t name) 287 | { 288 | const char *str = ctf_strptr (fp, name); 289 | ctf_id_t id = ctf_hash_lookup_type (hp, fp, str); 290 | 291 | if (id == 0) 292 | return (ctf_hash_insert_type (hp, fp, type, name)); 293 | 294 | return 0; 295 | } 296 | 297 | ctf_id_t 298 | ctf_hash_lookup_type (ctf_hash_t *hp, ctf_file_t *fp, const char *key) 299 | { 300 | ctf_helem_t *hep; 301 | ctf_strs_t *ctsp; 302 | const char *str; 303 | size_t i; 304 | size_t j = 0; 305 | 306 | uint32_t h = ctf_hash_string (key) % hp->h_nbuckets; 307 | 308 | for (i = hp->h_buckets[h]; i != 0; i = hep->h_next, j++) 309 | { 310 | hep = &hp->h_chains[i]; 311 | ctsp = &fp->ctf_str[CTF_NAME_STID (hep->h_name)]; 312 | str = ctsp->cts_strs + CTF_NAME_OFFSET (hep->h_name); 313 | if (strcmp (key, str) == 0) 314 | return hep->h_type; 315 | } 316 | 317 | return 0; /* Sentinel value. */ 318 | } 319 | 320 | void 321 | ctf_hash_destroy (ctf_hash_t *hp) 322 | { 323 | if (hp == NULL) 324 | return; 325 | 326 | if (hp->h_buckets != NULL && hp->h_nbuckets != 1) 327 | { 328 | free (hp->h_buckets); 329 | hp->h_buckets = NULL; 330 | } 331 | 332 | if (hp->h_chains != NULL) 333 | { 334 | free (hp->h_chains); 335 | hp->h_chains = NULL; 336 | } 337 | free (hp); 338 | } 339 | -------------------------------------------------------------------------------- /libctf/ctf-labels.c: -------------------------------------------------------------------------------- 1 | /* Labelled ranges of type IDs. 2 | Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. 3 | 4 | Licensed under the Universal Permissive License v 1.0 as shown at 5 | http://oss.oracle.com/licenses/upl. 6 | 7 | Licensed under the GNU General Public License (GPL), version 2. See the file 8 | COPYING in the top level of this tree. */ 9 | 10 | #include 11 | #include 12 | 13 | static int 14 | extract_label_info (ctf_file_t *fp, const ctf_lblent_t **ctl, 15 | uint32_t *num_labels) 16 | { 17 | const ctf_header_t *h; 18 | 19 | h = (const ctf_header_t *) fp->ctf_data.cts_data; 20 | 21 | *ctl = (const ctf_lblent_t *) (fp->ctf_buf + h->cth_lbloff); 22 | *num_labels = (h->cth_objtoff - h->cth_lbloff) / sizeof (ctf_lblent_t); 23 | 24 | return 0; 25 | } 26 | 27 | /* Returns the topmost label, or NULL if any errors are encountered. */ 28 | 29 | const char * 30 | ctf_label_topmost (ctf_file_t *fp) 31 | { 32 | const ctf_lblent_t *ctlp = NULL; 33 | const char *s; 34 | uint32_t num_labels = 0; 35 | 36 | if (extract_label_info (fp, &ctlp, &num_labels) < 0) 37 | return NULL; /* errno is set for us. */ 38 | 39 | if (num_labels == 0) 40 | { 41 | (void) ctf_set_errno (fp, ECTF_NOLABELDATA); 42 | return NULL; 43 | } 44 | 45 | if ((s = ctf_strraw (fp, (ctlp + num_labels - 1)->ctl_label)) == NULL) 46 | (void) ctf_set_errno (fp, ECTF_CORRUPT); 47 | 48 | return s; 49 | } 50 | 51 | /* Iterate over all labels. We pass the label string and the lblinfo_t struct 52 | to the specified callback function. */ 53 | int 54 | ctf_label_iter (ctf_file_t *fp, ctf_label_f *func, void *arg) 55 | { 56 | const ctf_lblent_t *ctlp = NULL; 57 | uint32_t i; 58 | uint32_t num_labels = 0; 59 | ctf_lblinfo_t linfo; 60 | const char *lname; 61 | int rc; 62 | 63 | if (extract_label_info (fp, &ctlp, &num_labels) < 0) 64 | return -1; /* errno is set for us. */ 65 | 66 | if (num_labels == 0) 67 | return (ctf_set_errno (fp, ECTF_NOLABELDATA)); 68 | 69 | for (i = 0; i < num_labels; i++, ctlp++) 70 | { 71 | if ((lname = ctf_strraw (fp, ctlp->ctl_label)) == NULL) 72 | { 73 | ctf_dprintf ("failed to decode label %u with " 74 | "type %u\n", ctlp->ctl_label, ctlp->ctl_type); 75 | return (ctf_set_errno (fp, ECTF_CORRUPT)); 76 | } 77 | 78 | linfo.ctb_type = ctlp->ctl_type; 79 | if ((rc = func (lname, &linfo, arg)) != 0) 80 | return rc; 81 | } 82 | 83 | return 0; 84 | } 85 | 86 | typedef struct linfo_cb_arg 87 | { 88 | const char *lca_name; /* Label we want to retrieve info for. */ 89 | ctf_lblinfo_t *lca_info; /* Where to store the info about the label. */ 90 | } linfo_cb_arg_t; 91 | 92 | static int 93 | label_info_cb (const char *lname, const ctf_lblinfo_t *linfo, void *arg) 94 | { 95 | /* If lname matches the label we are looking for, copy the 96 | lblinfo_t struct for the caller. */ 97 | 98 | if (strcmp (lname, ((linfo_cb_arg_t *) arg)->lca_name) == 0) 99 | { 100 | /* * Allow caller not to allocate storage to test if label exists. */ 101 | 102 | if (((linfo_cb_arg_t *) arg)->lca_info != NULL) 103 | memcpy (((linfo_cb_arg_t *) arg)->lca_info, linfo, 104 | sizeof (ctf_lblinfo_t)); 105 | return 1; /* Indicate we found a match. */ 106 | } 107 | 108 | return 0; 109 | } 110 | 111 | /* Retrieve information about the label with name "lname". */ 112 | int 113 | ctf_label_info (ctf_file_t *fp, const char *lname, ctf_lblinfo_t *linfo) 114 | { 115 | linfo_cb_arg_t cb_arg; 116 | int rc; 117 | 118 | cb_arg.lca_name = lname; 119 | cb_arg.lca_info = linfo; 120 | 121 | if ((rc = ctf_label_iter (fp, label_info_cb, &cb_arg)) < 0) 122 | return rc; 123 | 124 | if (rc != 1) 125 | return (ctf_set_errno (fp, ECTF_NOLABEL)); 126 | 127 | return 0; 128 | } 129 | -------------------------------------------------------------------------------- /libctf/ctf-lookup.c: -------------------------------------------------------------------------------- 1 | /* Symbol, variable and name lookup. 2 | Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved. 3 | 4 | Licensed under the Universal Permissive License v 1.0 as shown at 5 | http://oss.oracle.com/licenses/upl. 6 | 7 | Licensed under the GNU General Public License (GPL), version 2. See the file 8 | COPYING in the top level of this tree. */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | /* Compare the given input string and length against a table of known C storage 15 | qualifier keywords. We just ignore these in ctf_lookup_by_name, below. To 16 | do this quickly, we use a pre-computed Perfect Hash Function similar to the 17 | technique originally described in the classic paper: 18 | 19 | R.J. Cichelli, "Minimal Perfect Hash Functions Made Simple", 20 | Communications of the ACM, Volume 23, Issue 1, January 1980, pp. 17-19. 21 | 22 | For an input string S of length N, we use hash H = S[N - 1] + N - 105, which 23 | for the current set of qualifiers yields a unique H in the range [0 .. 20]. 24 | The hash can be modified when the keyword set changes as necessary. We also 25 | store the length of each keyword and check it prior to the final strcmp(). 26 | 27 | TODO: just use gperf. */ 28 | 29 | static int 30 | isqualifier (const char *s, size_t len) 31 | { 32 | static const struct qual 33 | { 34 | const char *q_name; 35 | size_t q_len; 36 | } qhash[] = { 37 | {"static", 6}, {"", 0}, {"", 0}, {"", 0}, 38 | {"volatile", 8}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, 39 | {"", 0}, {"auto", 4}, {"extern", 6}, {"", 0}, {"", 0}, 40 | {"", 0}, {"", 0}, {"const", 5}, {"register", 8}, 41 | {"", 0}, {"restrict", 8}, {"_Restrict", 9} 42 | }; 43 | 44 | int h = s[len - 1] + (int) len - 105; 45 | const struct qual *qp = &qhash[h]; 46 | 47 | return (h >= 0 && (size_t) h < sizeof (qhash) / sizeof (qhash[0]) 48 | && (size_t) len == qp->q_len && 49 | strncmp (qp->q_name, s, qp->q_len) == 0); 50 | } 51 | 52 | /* Attempt to convert the given C type name into the corresponding CTF type ID. 53 | It is not possible to do complete and proper conversion of type names 54 | without implementing a more full-fledged parser, which is necessary to 55 | handle things like types that are function pointers to functions that 56 | have arguments that are function pointers, and fun stuff like that. 57 | Instead, this function implements a very simple conversion algorithm that 58 | finds the things that we actually care about: structs, unions, enums, 59 | integers, floats, typedefs, and pointers to any of these named types. */ 60 | 61 | ctf_id_t 62 | ctf_lookup_by_name (ctf_file_t *fp, const char *name) 63 | { 64 | static const char delimiters[] = " \t\n\r\v\f*"; 65 | 66 | const ctf_lookup_t *lp; 67 | const char *p, *q, *end; 68 | ctf_id_t type = 0; 69 | ctf_id_t ntype, ptype; 70 | 71 | if (name == NULL) 72 | return (ctf_set_errno (fp, EINVAL)); 73 | 74 | for (p = name, end = name + strlen (name); *p != '\0'; p = q) 75 | { 76 | while (isspace (*p)) 77 | p++; /* Skip leading whitespace. */ 78 | 79 | if (p == end) 80 | break; 81 | 82 | if ((q = strpbrk (p + 1, delimiters)) == NULL) 83 | q = end; /* Compare until end. */ 84 | 85 | if (*p == '*') 86 | { 87 | /* Find a pointer to type by looking in fp->ctf_ptrtab. 88 | If we can't find a pointer to the given type, see if 89 | we can compute a pointer to the type resulting from 90 | resolving the type down to its base type and use 91 | that instead. This helps with cases where the CTF 92 | data includes "struct foo *" but not "foo_t *" and 93 | the user tries to access "foo_t *" in the debugger. 94 | 95 | TODO need to handle parent containers too. */ 96 | 97 | ntype = fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX (fp, type)]; 98 | if (ntype == 0) 99 | { 100 | ntype = ctf_type_resolve_unsliced (fp, type); 101 | if (ntype == CTF_ERR 102 | || (ntype = 103 | fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX (fp, ntype)]) == 0) 104 | { 105 | (void) ctf_set_errno (fp, ECTF_NOTYPE); 106 | goto err; 107 | } 108 | } 109 | 110 | type = LCTF_INDEX_TO_TYPE (fp, ntype, (fp->ctf_flags & LCTF_CHILD)); 111 | 112 | q = p + 1; 113 | continue; 114 | } 115 | 116 | if (isqualifier (p, (size_t) (q - p))) 117 | continue; /* Skip qualifier keyword. */ 118 | 119 | for (lp = fp->ctf_lookups; lp->ctl_prefix != NULL; lp++) 120 | { 121 | /* TODO: This is not MT-safe. */ 122 | if ((lp->ctl_prefix[0] == '\0' || 123 | strncmp (p, lp->ctl_prefix, (size_t) (q - p)) == 0) && 124 | (size_t) (q - p) >= lp->ctl_len) 125 | { 126 | for (p += lp->ctl_len; isspace (*p); p++) 127 | continue; /* Skip prefix and next whitespace. */ 128 | 129 | if ((q = strchr (p, '*')) == NULL) 130 | q = end; /* Compare until end. */ 131 | 132 | while (isspace (q[-1])) 133 | q--; /* Exclude trailing whitespace. */ 134 | 135 | /* Expand and/or allocate storage for a slice of the name, then 136 | copy it in. */ 137 | 138 | if (fp->ctf_tmp_typeslicelen >= (size_t) (q - p) + 1) 139 | { 140 | memcpy (fp->ctf_tmp_typeslice, p, (size_t) (q - p)); 141 | fp->ctf_tmp_typeslice[(size_t) (q - p)] = '\0'; 142 | } 143 | else 144 | { 145 | free (fp->ctf_tmp_typeslice); 146 | fp->ctf_tmp_typeslice = xstrndup (p, (size_t) (q - p)); 147 | if (fp->ctf_tmp_typeslice == NULL) 148 | { 149 | (void) ctf_set_errno (fp, ENOMEM); 150 | return CTF_ERR; 151 | } 152 | } 153 | 154 | if ((type = ctf_lookup_by_rawhash (fp, lp->ctl_hash, 155 | fp->ctf_tmp_typeslice)) == 0) 156 | { 157 | (void) ctf_set_errno (fp, ECTF_NOTYPE); 158 | goto err; 159 | } 160 | 161 | break; 162 | } 163 | } 164 | 165 | if (lp->ctl_prefix == NULL) 166 | { 167 | (void) ctf_set_errno (fp, ECTF_NOTYPE); 168 | goto err; 169 | } 170 | } 171 | 172 | if (*p != '\0' || type == 0) 173 | return (ctf_set_errno (fp, ECTF_SYNTAX)); 174 | 175 | return type; 176 | 177 | err: 178 | if (fp->ctf_parent != NULL 179 | && (ptype = ctf_lookup_by_name (fp->ctf_parent, name)) != CTF_ERR) 180 | return ptype; 181 | 182 | return CTF_ERR; 183 | } 184 | 185 | typedef struct ctf_lookup_var_key 186 | { 187 | ctf_file_t *clvk_fp; 188 | const char *clvk_name; 189 | } ctf_lookup_var_key_t; 190 | 191 | /* A bsearch function for variable names. */ 192 | 193 | static int 194 | ctf_lookup_var (const void *key_, const void *memb_) 195 | { 196 | const ctf_lookup_var_key_t *key = key_; 197 | const ctf_varent_t *memb = memb_; 198 | 199 | return (strcmp (key->clvk_name, ctf_strptr (key->clvk_fp, memb->ctv_name))); 200 | } 201 | 202 | /* Given a variable name, return the type of the variable with that name. */ 203 | 204 | ctf_id_t 205 | ctf_lookup_variable (ctf_file_t *fp, const char *name) 206 | { 207 | ctf_varent_t *ent; 208 | ctf_lookup_var_key_t key = { fp, name }; 209 | 210 | /* This array is sorted, so we can bsearch for it. */ 211 | 212 | ent = bsearch (&key, fp->ctf_vars, fp->ctf_nvars, sizeof (ctf_varent_t), 213 | ctf_lookup_var); 214 | 215 | if (ent == NULL) 216 | { 217 | if (fp->ctf_parent != NULL) 218 | return ctf_lookup_variable (fp->ctf_parent, name); 219 | 220 | return (ctf_set_errno (fp, ECTF_NOTYPEDAT)); 221 | } 222 | 223 | return ent->ctv_type; 224 | } 225 | 226 | /* Given a symbol table index, return the name of that symbol from the secondary 227 | string table, or the null string (never NULL). */ 228 | const char * 229 | ctf_lookup_symbol_name (ctf_file_t *fp, unsigned long symidx) 230 | { 231 | const ctf_sect_t *sp = &fp->ctf_symtab; 232 | Elf64_Sym sym, *gsp; 233 | 234 | if (sp->cts_data == NULL) 235 | { 236 | ctf_set_errno (fp, ECTF_NOSYMTAB); 237 | return _CTF_NULLSTR; 238 | } 239 | 240 | if (symidx >= fp->ctf_nsyms) 241 | { 242 | ctf_set_errno (fp, EINVAL); 243 | return _CTF_NULLSTR; 244 | } 245 | 246 | if (sp->cts_entsize == sizeof (Elf32_Sym)) 247 | { 248 | const Elf32_Sym *symp = (Elf32_Sym *) sp->cts_data + symidx; 249 | gsp = ctf_sym_to_elf64 (symp, &sym); 250 | } 251 | else 252 | gsp = (Elf64_Sym *) sp->cts_data + symidx; 253 | 254 | if (gsp->st_name < fp->ctf_str[CTF_STRTAB_1].cts_len) 255 | return (const char *) fp->ctf_str[CTF_STRTAB_1].cts_strs + gsp->st_name; 256 | 257 | return _CTF_NULLSTR; 258 | } 259 | 260 | /* Given a symbol table index, return the type of the data object described 261 | by the corresponding entry in the symbol table. */ 262 | 263 | ctf_id_t 264 | ctf_lookup_by_symbol (ctf_file_t *fp, unsigned long symidx) 265 | { 266 | const ctf_sect_t *sp = &fp->ctf_symtab; 267 | ctf_id_t type; 268 | 269 | if (sp->cts_data == NULL) 270 | return (ctf_set_errno (fp, ECTF_NOSYMTAB)); 271 | 272 | if (symidx >= fp->ctf_nsyms) 273 | return (ctf_set_errno (fp, EINVAL)); 274 | 275 | if (sp->cts_entsize == sizeof (Elf32_Sym)) 276 | { 277 | const Elf32_Sym *symp = (Elf32_Sym *) sp->cts_data + symidx; 278 | if (ELF32_ST_TYPE (symp->st_info) != STT_OBJECT) 279 | return (ctf_set_errno (fp, ECTF_NOTDATA)); 280 | } 281 | else 282 | { 283 | const Elf64_Sym *symp = (Elf64_Sym *) sp->cts_data + symidx; 284 | if (ELF64_ST_TYPE (symp->st_info) != STT_OBJECT) 285 | return (ctf_set_errno (fp, ECTF_NOTDATA)); 286 | } 287 | 288 | if (fp->ctf_sxlate[symidx] == -1u) 289 | return (ctf_set_errno (fp, ECTF_NOTYPEDAT)); 290 | 291 | type = *(uint32_t *) ((uintptr_t) fp->ctf_buf + fp->ctf_sxlate[symidx]); 292 | if (type == 0) 293 | return (ctf_set_errno (fp, ECTF_NOTYPEDAT)); 294 | 295 | return type; 296 | } 297 | 298 | /* Return the pointer to the internal CTF type data corresponding to the 299 | given type ID. If the ID is invalid, the function returns NULL. 300 | This function is not exported outside of the library. */ 301 | 302 | const ctf_type_t * 303 | ctf_lookup_by_id (ctf_file_t **fpp, ctf_id_t type) 304 | { 305 | ctf_file_t *fp = *fpp; /* Caller passes in starting CTF container. */ 306 | ctf_id_t idx; 307 | 308 | if ((fp->ctf_flags & LCTF_CHILD) && LCTF_TYPE_ISPARENT (fp, type) 309 | && (fp = fp->ctf_parent) == NULL) 310 | { 311 | (void) ctf_set_errno (*fpp, ECTF_NOPARENT); 312 | return NULL; 313 | } 314 | 315 | /* If this container is writable, check for a dynamic type. */ 316 | 317 | if (fp->ctf_flags & LCTF_RDWR) 318 | { 319 | ctf_dtdef_t *dtd; 320 | 321 | if ((dtd = ctf_dynamic_type (fp, type)) != NULL) 322 | { 323 | *fpp = fp; 324 | return &dtd->dtd_data; 325 | } 326 | (void) ctf_set_errno (*fpp, ECTF_BADID); 327 | return NULL; 328 | } 329 | 330 | /* Check for a type in the static portion. */ 331 | 332 | idx = LCTF_TYPE_TO_INDEX (fp, type); 333 | if (idx > 0 && (unsigned long) idx <= fp->ctf_typemax) 334 | { 335 | *fpp = fp; /* Function returns ending CTF container. */ 336 | return (LCTF_INDEX_TO_TYPEPTR (fp, idx)); 337 | } 338 | 339 | (void) ctf_set_errno (*fpp, ECTF_BADID); 340 | return NULL; 341 | } 342 | 343 | /* Given a symbol table index, return the info for the function described 344 | by the corresponding entry in the symbol table. */ 345 | 346 | int 347 | ctf_func_info (ctf_file_t *fp, unsigned long symidx, ctf_funcinfo_t *fip) 348 | { 349 | const ctf_sect_t *sp = &fp->ctf_symtab; 350 | const uint32_t *dp; 351 | uint32_t info, kind, n; 352 | 353 | if (sp->cts_data == NULL) 354 | return (ctf_set_errno (fp, ECTF_NOSYMTAB)); 355 | 356 | if (symidx >= fp->ctf_nsyms) 357 | return (ctf_set_errno (fp, EINVAL)); 358 | 359 | if (sp->cts_entsize == sizeof (Elf32_Sym)) 360 | { 361 | const Elf32_Sym *symp = (Elf32_Sym *) sp->cts_data + symidx; 362 | if (ELF32_ST_TYPE (symp->st_info) != STT_FUNC) 363 | return (ctf_set_errno (fp, ECTF_NOTFUNC)); 364 | } 365 | else 366 | { 367 | const Elf64_Sym *symp = (Elf64_Sym *) sp->cts_data + symidx; 368 | if (ELF64_ST_TYPE (symp->st_info) != STT_FUNC) 369 | return (ctf_set_errno (fp, ECTF_NOTFUNC)); 370 | } 371 | 372 | if (fp->ctf_sxlate[symidx] == -1u) 373 | return (ctf_set_errno (fp, ECTF_NOFUNCDAT)); 374 | 375 | dp = (uint32_t *) ((uintptr_t) fp->ctf_buf + fp->ctf_sxlate[symidx]); 376 | 377 | info = *dp++; 378 | kind = LCTF_INFO_KIND (fp, info); 379 | n = LCTF_INFO_VLEN (fp, info); 380 | 381 | if (kind == CTF_K_UNKNOWN && n == 0) 382 | return (ctf_set_errno (fp, ECTF_NOFUNCDAT)); 383 | 384 | if (kind != CTF_K_FUNCTION) 385 | return (ctf_set_errno (fp, ECTF_CORRUPT)); 386 | 387 | fip->ctc_return = *dp++; 388 | fip->ctc_argc = n; 389 | fip->ctc_flags = 0; 390 | 391 | if (n != 0 && dp[n - 1] == 0) 392 | { 393 | fip->ctc_flags |= CTF_FUNC_VARARG; 394 | fip->ctc_argc--; 395 | } 396 | 397 | return 0; 398 | } 399 | 400 | /* Given a symbol table index, return the arguments for the function described 401 | by the corresponding entry in the symbol table. */ 402 | 403 | int 404 | ctf_func_args (ctf_file_t * fp, unsigned long symidx, uint32_t argc, 405 | ctf_id_t * argv) 406 | { 407 | const uint32_t *dp; 408 | ctf_funcinfo_t f; 409 | 410 | if (ctf_func_info (fp, symidx, &f) < 0) 411 | return -1; /* errno is set for us. */ 412 | 413 | /* The argument data is two uint32_t's past the translation table 414 | offset: one for the function info, and one for the return type. */ 415 | 416 | dp = (uint32_t *) ((uintptr_t) fp->ctf_buf + fp->ctf_sxlate[symidx]) + 2; 417 | 418 | for (argc = MIN (argc, f.ctc_argc); argc != 0; argc--) 419 | *argv++ = *dp++; 420 | 421 | return 0; 422 | } 423 | -------------------------------------------------------------------------------- /libctf/ctf-open-bfd.c: -------------------------------------------------------------------------------- 1 | /* Opening CTF files with BFD. 2 | Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved. 3 | 4 | Licensed under the Universal Permissive License v 1.0 as shown at 5 | http://oss.oracle.com/licenses/upl. 6 | 7 | Licensed under the GNU General Public License (GPL), version 2. See the file 8 | COPYING in the top level of this tree. */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "swap.h" 22 | #include "ctf-endian.h" 23 | 24 | #ifdef BFD_ONLY 25 | #include "elf-bfd.h" 26 | #else 27 | #define SHN_EXTABS SHN_ABS 28 | #endif 29 | 30 | /* Free the BFD bits of a CTF file on ctf_arc_close(). */ 31 | 32 | static void 33 | ctf_bfdclose (struct ctf_archive_internal *arci) 34 | { 35 | if (arci->ctfi_abfd != NULL) 36 | if (!bfd_close_all_done (arci->ctfi_abfd)) 37 | ctf_dprintf ("Cannot close BFD: %s\n", bfd_errmsg (bfd_get_error())); 38 | } 39 | 40 | /* Open a CTF file given the specified BFD. */ 41 | 42 | ctf_archive_t * 43 | ctf_bfdopen (struct bfd *abfd, int *errp) 44 | { 45 | ctf_archive_t *arc; 46 | asection *ctf_asect; 47 | bfd_byte *contents; 48 | ctf_sect_t ctfsect; 49 | 50 | libctf_init_debug(); 51 | 52 | if ((ctf_asect = bfd_get_section_by_name (abfd, _CTF_SECTION)) == NULL) 53 | { 54 | return (ctf_set_open_errno (errp, ECTF_NOCTFDATA)); 55 | } 56 | 57 | if (!bfd_malloc_and_get_section (abfd, ctf_asect, &contents)) 58 | { 59 | ctf_dprintf ("ctf_bfdopen(): cannot malloc CTF section: %s\n", 60 | bfd_errmsg (bfd_get_error())); 61 | return (ctf_set_open_errno (errp, ECTF_FMT)); 62 | } 63 | 64 | ctfsect.cts_name = _CTF_SECTION; 65 | ctfsect.cts_entsize = 1; 66 | ctfsect.cts_size = bfd_section_size (ctf_asect); 67 | ctfsect.cts_data = contents; 68 | 69 | if ((arc = ctf_bfdopen_ctfsect (abfd, &ctfsect, errp)) != NULL) 70 | { 71 | /* This frees the cts_data later. */ 72 | arc->ctfi_data = (void *) ctfsect.cts_data; 73 | return arc; 74 | } 75 | 76 | free (contents); 77 | return NULL; /* errno is set for us. */ 78 | } 79 | 80 | /* Open a CTF file given the specified BFD and CTF section (which may contain a 81 | CTF archive or a file). */ 82 | 83 | ctf_archive_t * 84 | ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_, 85 | const ctf_sect_t *ctfsect, int *errp) 86 | { 87 | ctf_archive_t *arci; 88 | ctf_sect_t *symsectp = NULL; 89 | ctf_sect_t *strsectp = NULL; 90 | const char *bfderrstr = NULL; 91 | 92 | #ifdef HAVE_BFD_ELF 93 | ctf_sect_t symsect, strsect; 94 | Elf_Internal_Shdr *strhdr; 95 | Elf_Internal_Shdr *symhdr = &elf_symtab_hdr (abfd); 96 | size_t symcount = symhdr->sh_size / symhdr->sh_entsize; 97 | Elf_Internal_Sym *isymbuf; 98 | bfd_byte *symtab; 99 | const char *strtab = NULL; 100 | /* TODO: handle SYMTAB_SHNDX. */ 101 | 102 | if ((symtab = malloc (symhdr->sh_size)) == NULL) 103 | { 104 | bfderrstr = "Cannot malloc symbol table"; 105 | goto err; 106 | } 107 | 108 | isymbuf = bfd_elf_get_elf_syms (abfd, symhdr, symcount, 0, 109 | NULL, symtab, NULL); 110 | free (isymbuf); 111 | if (isymbuf == NULL) 112 | { 113 | bfderrstr = "Cannot read symbol table"; 114 | goto err_free_sym; 115 | } 116 | 117 | if (elf_elfsections (abfd) != NULL 118 | && symhdr->sh_link < elf_numsections (abfd)) 119 | { 120 | strhdr = elf_elfsections (abfd)[symhdr->sh_link]; 121 | if (strhdr->contents == NULL) 122 | { 123 | if ((strtab = bfd_elf_get_str_section (abfd, symhdr->sh_link)) == NULL) 124 | { 125 | bfderrstr = "Cannot read string table"; 126 | goto err_free_sym; 127 | } 128 | } 129 | else 130 | strtab = (const char *) strhdr->contents; 131 | } 132 | 133 | if (strtab) 134 | { 135 | /* The names here are more or less arbitrary, but there is no point 136 | thrashing around digging the name out of the shstrtab given that we don't 137 | use it for anything but debugging. */ 138 | 139 | strsect.cts_data = strtab; 140 | strsect.cts_name = ".strtab"; 141 | strsect.cts_size = strhdr->sh_size; 142 | strsectp = &strsect; 143 | 144 | assert (symhdr->sh_entsize == get_elf_backend_data (abfd)->s->sizeof_sym); 145 | symsect.cts_name = ".symtab"; 146 | symsect.cts_entsize = symhdr->sh_entsize; 147 | symsect.cts_size = symhdr->sh_size; 148 | symsect.cts_data = symtab; 149 | symsectp = &symsect; 150 | } 151 | #endif 152 | 153 | arci = ctf_arc_bufopen (ctfsect, symsectp, strsectp, errp); 154 | if (arci) 155 | { 156 | /* Request freeing of the symsect. */ 157 | arci->ctfi_free_symsect = 1; 158 | return arci; 159 | } 160 | #ifdef HAVE_BFD_ELF 161 | err_free_sym: 162 | free (symtab); 163 | #endif 164 | err: _libctf_unused_; 165 | if (bfderrstr) 166 | { 167 | ctf_dprintf ("ctf_bfdopen(): %s: %s\n", bfderrstr, 168 | bfd_errmsg (bfd_get_error())); 169 | ctf_set_open_errno (errp, ECTF_FMT); 170 | } 171 | return NULL; 172 | } 173 | 174 | /* Open the specified file descriptor and return a pointer to a CTF archive that 175 | contains one or more CTF containers. The file can be an ELF file, a raw CTF 176 | file, or a CTF archive. The caller is responsible for closing the file 177 | descriptor when it is no longer needed. If this is an ELF file, TARGET, if 178 | non-NULL, should be the name of a suitable BFD target. */ 179 | 180 | ctf_archive_t * 181 | ctf_fdopen (int fd, const char *filename, const char *target, int *errp) 182 | { 183 | ctf_archive_t *arci; 184 | bfd *abfd; 185 | int nfd; 186 | 187 | struct stat st; 188 | ssize_t nbytes; 189 | 190 | ctf_preamble_t ctfhdr; 191 | uint64_t arc_magic; 192 | 193 | memset (&ctfhdr, 0, sizeof (ctfhdr)); 194 | 195 | libctf_init_debug(); 196 | 197 | if (fstat (fd, &st) == -1) 198 | return (ctf_set_open_errno (errp, errno)); 199 | 200 | if ((nbytes = ctf_pread (fd, &ctfhdr, sizeof (ctfhdr), 0)) <= 0) 201 | return (ctf_set_open_errno (errp, nbytes < 0 ? errno : ECTF_FMT)); 202 | 203 | /* If we have read enough bytes to form a CTF header and the magic string 204 | matches, in either endianness, attempt to interpret the file as raw 205 | CTF. */ 206 | 207 | if ((size_t) nbytes >= sizeof (ctf_preamble_t) 208 | && (ctfhdr.ctp_magic == CTF_MAGIC 209 | || ctfhdr.ctp_magic == bswap_16 (CTF_MAGIC))) 210 | { 211 | ctf_file_t *fp = NULL; 212 | void *data; 213 | 214 | if ((data = ctf_mmap (st.st_size, 0, fd)) == NULL) 215 | return (ctf_set_open_errno (errp, errno)); 216 | 217 | if ((fp = ctf_simple_open (data, (size_t) st.st_size, NULL, 0, 0, 218 | NULL, 0, errp)) == NULL) 219 | { 220 | ctf_munmap (data, (size_t) st.st_size); 221 | return NULL; /* errno is set for us. */ 222 | } 223 | 224 | fp->ctf_data_mmapped = data; 225 | fp->ctf_data_mmapped_len = (size_t) st.st_size; 226 | 227 | return ctf_new_archive_internal (0, NULL, fp, NULL, NULL, errp); 228 | } 229 | 230 | if ((nbytes = ctf_pread (fd, &arc_magic, sizeof (arc_magic), 0)) <= 0) 231 | return (ctf_set_open_errno (errp, nbytes < 0 ? errno : ECTF_FMT)); 232 | 233 | if ((size_t) nbytes >= sizeof (uint64_t) && le64toh (arc_magic) == CTFA_MAGIC) 234 | { 235 | struct ctf_archive *arc; 236 | 237 | if ((arc = ctf_arc_open_internal (filename, errp)) == NULL) 238 | return NULL; /* errno is set for us. */ 239 | 240 | return ctf_new_archive_internal (1, arc, NULL, NULL, NULL, errp); 241 | } 242 | 243 | /* Attempt to open the file with BFD. We must dup the fd first, since bfd 244 | takes ownership of the passed fd. */ 245 | 246 | if ((nfd = dup (fd)) < 0) 247 | return (ctf_set_open_errno (errp, errno)); 248 | 249 | if ((abfd = bfd_fdopenr (filename, target, nfd)) == NULL) 250 | { 251 | ctf_dprintf ("Cannot open BFD from %s: %s\n", 252 | filename ? filename : "(unknown file)", 253 | bfd_errmsg (bfd_get_error())); 254 | return (ctf_set_open_errno (errp, ECTF_FMT)); 255 | } 256 | bfd_set_cacheable (abfd, 1); 257 | 258 | if (!bfd_check_format (abfd, bfd_object)) 259 | { 260 | ctf_dprintf ("BFD format problem in %s: %s\n", 261 | filename ? filename : "(unknown file)", 262 | bfd_errmsg (bfd_get_error())); 263 | if (bfd_get_error() == bfd_error_file_ambiguously_recognized) 264 | return (ctf_set_open_errno (errp, ECTF_BFD_AMBIGUOUS)); 265 | else 266 | return (ctf_set_open_errno (errp, ECTF_FMT)); 267 | } 268 | 269 | if ((arci = ctf_bfdopen (abfd, errp)) == NULL) 270 | { 271 | if (!bfd_close_all_done (abfd)) 272 | ctf_dprintf ("Cannot close BFD: %s\n", bfd_errmsg (bfd_get_error())); 273 | return NULL; /* errno is set for us. */ 274 | } 275 | arci->ctfi_bfd_close = ctf_bfdclose; 276 | arci->ctfi_abfd = abfd; 277 | 278 | return arci; 279 | } 280 | 281 | /* Open the specified file and return a pointer to a CTF container. The file 282 | can be either an ELF file or raw CTF file. This is just a convenient 283 | wrapper around ctf_fdopen() for callers. */ 284 | 285 | ctf_archive_t * 286 | ctf_open (const char *filename, const char *target, int *errp) 287 | { 288 | ctf_archive_t *arc; 289 | int fd; 290 | 291 | if ((fd = open (filename, O_RDONLY)) == -1) 292 | { 293 | if (errp != NULL) 294 | *errp = errno; 295 | return NULL; 296 | } 297 | 298 | arc = ctf_fdopen (fd, filename, target, errp); 299 | (void) close (fd); 300 | return arc; 301 | } 302 | 303 | /* Public entry point: open a CTF archive, or CTF file. Returns the archive, or 304 | NULL and an error in *err. Despite the fact that this uses CTF archives, it 305 | must be in this file to avoid dragging in BFD into non-BFD-using programs. */ 306 | ctf_archive_t * 307 | ctf_arc_open (const char *filename, int *errp) 308 | { 309 | return ctf_open (filename, NULL, errp); 310 | } 311 | -------------------------------------------------------------------------------- /libctf/ctf-string.c: -------------------------------------------------------------------------------- 1 | /* CTF string table management. 2 | Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 3 | 4 | Licensed under the Universal Permissive License v 1.0 as shown at 5 | http://oss.oracle.com/licenses/upl. 6 | 7 | Licensed under the GNU General Public License (GPL), version 2. See the file 8 | COPYING in the top level of this tree. */ 9 | 10 | #include 11 | #include 12 | 13 | /* Convert an encoded CTF string name into a pointer to a C string, using an 14 | explicit internal strtab rather than the fp-based one. */ 15 | const char * 16 | ctf_strraw_explicit (ctf_file_t *fp, uint32_t name, ctf_strs_t *strtab) 17 | { 18 | ctf_strs_t *ctsp = &fp->ctf_str[CTF_NAME_STID (name)]; 19 | 20 | if ((CTF_NAME_STID (name) == CTF_STRTAB_0) && (strtab != NULL)) 21 | ctsp = strtab; 22 | 23 | /* If this name is in the external strtab, and there is a synthetic strtab, 24 | use it in preference. */ 25 | 26 | if (CTF_NAME_STID (name) == CTF_STRTAB_1 27 | && fp->ctf_syn_ext_strtab != NULL) 28 | return ctf_dynhash_lookup (fp->ctf_syn_ext_strtab, 29 | (void *) (uintptr_t) name); 30 | 31 | /* If the name is in the internal strtab, and the offset is beyond the end of 32 | the ctsp->cts_len but below the ctf_str_prov_offset, this is a provisional 33 | string added by ctf_str_add*() but not yet built into a real strtab: get 34 | the value out of the ctf_prov_strtab. */ 35 | 36 | if (CTF_NAME_STID (name) == CTF_STRTAB_0 37 | && name >= ctsp->cts_len && name < fp->ctf_str_prov_offset) 38 | return ctf_dynhash_lookup (fp->ctf_prov_strtab, 39 | (void *) (uintptr_t) name); 40 | 41 | if (ctsp->cts_strs != NULL && CTF_NAME_OFFSET (name) < ctsp->cts_len) 42 | return (ctsp->cts_strs + CTF_NAME_OFFSET (name)); 43 | 44 | /* String table not loaded or corrupt offset. */ 45 | return NULL; 46 | } 47 | 48 | /* Convert an encoded CTF string name into a pointer to a C string by looking 49 | up the appropriate string table buffer and then adding the offset. */ 50 | const char * 51 | ctf_strraw (ctf_file_t *fp, uint32_t name) 52 | { 53 | return ctf_strraw_explicit (fp, name, NULL); 54 | } 55 | 56 | /* Return a guaranteed-non-NULL pointer to the string with the given CTF 57 | name. */ 58 | const char * 59 | ctf_strptr (ctf_file_t *fp, uint32_t name) 60 | { 61 | const char *s = ctf_strraw (fp, name); 62 | return (s != NULL ? s : "(?)"); 63 | } 64 | 65 | /* Remove all refs to a given atom. */ 66 | static void 67 | ctf_str_purge_atom_refs (ctf_str_atom_t *atom) 68 | { 69 | ctf_str_atom_ref_t *ref, *next; 70 | 71 | for (ref = ctf_list_next (&atom->csa_refs); ref != NULL; ref = next) 72 | { 73 | next = ctf_list_next (ref); 74 | ctf_list_delete (&atom->csa_refs, ref); 75 | free (ref); 76 | } 77 | } 78 | 79 | /* Free an atom (only called on ctf_close().) */ 80 | static void 81 | ctf_str_free_atom (void *a) 82 | { 83 | ctf_str_atom_t *atom = a; 84 | 85 | ctf_str_purge_atom_refs (atom); 86 | free (atom); 87 | } 88 | 89 | /* Create the atoms table. There is always at least one atom in it, the null 90 | string. */ 91 | int 92 | ctf_str_create_atoms (ctf_file_t *fp) 93 | { 94 | fp->ctf_str_atoms = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string, 95 | free, ctf_str_free_atom); 96 | if (fp->ctf_str_atoms == NULL) 97 | return -ENOMEM; 98 | 99 | if (!fp->ctf_prov_strtab) 100 | fp->ctf_prov_strtab = ctf_dynhash_create (ctf_hash_integer, 101 | ctf_hash_eq_integer, 102 | NULL, NULL); 103 | if (!fp->ctf_prov_strtab) 104 | goto oom_prov_strtab; 105 | 106 | errno = 0; 107 | ctf_str_add (fp, ""); 108 | if (errno == ENOMEM) 109 | goto oom_str_add; 110 | 111 | return 0; 112 | 113 | oom_str_add: 114 | ctf_dynhash_destroy (fp->ctf_prov_strtab); 115 | fp->ctf_prov_strtab = NULL; 116 | oom_prov_strtab: 117 | ctf_dynhash_destroy (fp->ctf_str_atoms); 118 | fp->ctf_str_atoms = NULL; 119 | return -ENOMEM; 120 | } 121 | 122 | /* Destroy the atoms table. */ 123 | void 124 | ctf_str_free_atoms (ctf_file_t *fp) 125 | { 126 | ctf_dynhash_destroy (fp->ctf_prov_strtab); 127 | ctf_dynhash_destroy (fp->ctf_str_atoms); 128 | } 129 | 130 | /* Add a string to the atoms table, copying the passed-in string. Return the 131 | atom added. Return NULL only when out of memory (and do not touch the 132 | passed-in string in that case). Possibly augment the ref list with the 133 | passed-in ref. Possibly add a provisional entry for this string to the 134 | provisional strtab. */ 135 | static ctf_str_atom_t * 136 | ctf_str_add_ref_internal (ctf_file_t *fp, const char *str, 137 | int add_ref, int make_provisional, uint32_t *ref) 138 | { 139 | char *newstr = NULL; 140 | ctf_str_atom_t *atom = NULL; 141 | ctf_str_atom_ref_t *aref = NULL; 142 | 143 | atom = ctf_dynhash_lookup (fp->ctf_str_atoms, str); 144 | 145 | if (add_ref) 146 | { 147 | if ((aref = malloc (sizeof (struct ctf_str_atom_ref))) == NULL) 148 | return NULL; 149 | aref->caf_ref = ref; 150 | } 151 | 152 | if (atom) 153 | { 154 | if (add_ref) 155 | { 156 | ctf_list_append (&atom->csa_refs, aref); 157 | fp->ctf_str_num_refs++; 158 | } 159 | return atom; 160 | } 161 | 162 | if ((atom = malloc (sizeof (struct ctf_str_atom))) == NULL) 163 | goto oom; 164 | memset (atom, 0, sizeof (struct ctf_str_atom)); 165 | 166 | if ((newstr = strdup (str)) == NULL) 167 | goto oom; 168 | 169 | if (ctf_dynhash_insert (fp->ctf_str_atoms, newstr, atom) < 0) 170 | goto oom; 171 | 172 | atom->csa_str = newstr; 173 | atom->csa_snapshot_id = fp->ctf_snapshots; 174 | 175 | if (make_provisional) 176 | { 177 | atom->csa_offset = fp->ctf_str_prov_offset; 178 | 179 | if (ctf_dynhash_insert (fp->ctf_prov_strtab, (void *) (uintptr_t) 180 | atom->csa_offset, (void *) atom->csa_str) < 0) 181 | goto oom; 182 | 183 | fp->ctf_str_prov_offset += strlen (atom->csa_str) + 1; 184 | } 185 | 186 | if (add_ref) 187 | { 188 | ctf_list_append (&atom->csa_refs, aref); 189 | fp->ctf_str_num_refs++; 190 | } 191 | return atom; 192 | 193 | oom: 194 | if (newstr) 195 | ctf_dynhash_remove (fp->ctf_str_atoms, newstr); 196 | free (atom); 197 | free (aref); 198 | free (newstr); 199 | return NULL; 200 | } 201 | 202 | /* Add a string to the atoms table, without augmenting the ref list for this 203 | string: return a 'provisional offset' which can be used to return this string 204 | until ctf_str_write_strtab is called, or 0 on failure. (Everywhere the 205 | provisional offset is assigned to should be added as a ref using 206 | ctf_str_add_ref() as well.) */ 207 | uint32_t 208 | ctf_str_add (ctf_file_t *fp, const char *str) 209 | { 210 | ctf_str_atom_t *atom; 211 | if (!str) 212 | return 0; 213 | 214 | atom = ctf_str_add_ref_internal (fp, str, FALSE, TRUE, 0); 215 | if (!atom) 216 | return 0; 217 | 218 | return atom->csa_offset; 219 | } 220 | 221 | /* Like ctf_str_add(), but additionally augment the atom's refs list with the 222 | passed-in ref, whether or not the string is already present. There is no 223 | attempt to deduplicate the refs list (but duplicates are harmless). */ 224 | uint32_t 225 | ctf_str_add_ref (ctf_file_t *fp, const char *str, uint32_t *ref) 226 | { 227 | ctf_str_atom_t *atom; 228 | if (!str) 229 | return 0; 230 | 231 | atom = ctf_str_add_ref_internal (fp, str, TRUE, TRUE, ref); 232 | if (!atom) 233 | return 0; 234 | 235 | return atom->csa_offset; 236 | } 237 | 238 | /* Add an external strtab reference at OFFSET. Returns zero if the addition 239 | failed, nonzero otherwise. */ 240 | int 241 | ctf_str_add_external (ctf_file_t *fp, const char *str, uint32_t offset) 242 | { 243 | ctf_str_atom_t *atom; 244 | if (!str) 245 | return 0; 246 | 247 | atom = ctf_str_add_ref_internal (fp, str, FALSE, FALSE, 0); 248 | if (!atom) 249 | return 0; 250 | 251 | atom->csa_external_offset = CTF_SET_STID (offset, CTF_STRTAB_1); 252 | return 1; 253 | } 254 | 255 | /* Remove a single ref. */ 256 | void 257 | ctf_str_remove_ref (ctf_file_t *fp, const char *str, uint32_t *ref) 258 | { 259 | ctf_str_atom_ref_t *aref, *anext; 260 | ctf_str_atom_t *atom = NULL; 261 | 262 | atom = ctf_dynhash_lookup (fp->ctf_str_atoms, str); 263 | if (!atom) 264 | return; 265 | 266 | for (aref = ctf_list_next (&atom->csa_refs); aref != NULL; aref = anext) 267 | { 268 | anext = ctf_list_next (aref); 269 | if (aref->caf_ref == ref) 270 | { 271 | ctf_list_delete (&atom->csa_refs, aref); 272 | free (aref); 273 | } 274 | } 275 | } 276 | 277 | /* A ctf_dynhash_iter_remove() callback that removes atoms later than a given 278 | snapshot ID. */ 279 | static int 280 | ctf_str_rollback_atom (void *key _libctf_unused_, void *value, void *arg) 281 | { 282 | ctf_str_atom_t *atom = (ctf_str_atom_t *) value; 283 | ctf_snapshot_id_t *id = (ctf_snapshot_id_t *) arg; 284 | 285 | return (atom->csa_snapshot_id > id->snapshot_id); 286 | } 287 | 288 | /* Roll back, deleting all atoms created after a particular ID. */ 289 | void 290 | ctf_str_rollback (ctf_file_t *fp, ctf_snapshot_id_t id) 291 | { 292 | ctf_dynhash_iter_remove (fp->ctf_str_atoms, ctf_str_rollback_atom, &id); 293 | } 294 | 295 | /* An adaptor around ctf_purge_atom_refs. */ 296 | static void 297 | ctf_str_purge_one_atom_refs (void *key _libctf_unused_, void *value, 298 | void *arg _libctf_unused_) 299 | { 300 | ctf_str_atom_t *atom = (ctf_str_atom_t *) value; 301 | ctf_str_purge_atom_refs (atom); 302 | } 303 | 304 | /* Remove all the recorded refs from the atoms table. */ 305 | void 306 | ctf_str_purge_refs (ctf_file_t *fp) 307 | { 308 | if (fp->ctf_str_num_refs > 0) 309 | ctf_dynhash_iter (fp->ctf_str_atoms, ctf_str_purge_one_atom_refs, NULL); 310 | fp->ctf_str_num_refs = 0; 311 | } 312 | 313 | /* Update a list of refs to the specified value. */ 314 | static void 315 | ctf_str_update_refs (ctf_str_atom_t *refs, uint32_t value) 316 | { 317 | ctf_str_atom_ref_t *ref; 318 | 319 | for (ref = ctf_list_next (&refs->csa_refs); ref != NULL; 320 | ref = ctf_list_next (ref)) 321 | *(ref->caf_ref) = value; 322 | } 323 | 324 | /* State shared across the strtab write process. */ 325 | typedef struct ctf_strtab_write_state 326 | { 327 | /* Strtab we are writing, and the number of strings in it. */ 328 | ctf_strs_writable_t *strtab; 329 | size_t strtab_count; 330 | 331 | /* Pointers to (existing) atoms in the atoms table, for qsorting. */ 332 | ctf_str_atom_t **sorttab; 333 | 334 | /* Loop counter for sorttab population. */ 335 | size_t i; 336 | 337 | /* The null-string atom (skipped during population). */ 338 | ctf_str_atom_t *nullstr; 339 | } ctf_strtab_write_state_t; 340 | 341 | /* Count the number of entries in the strtab, and its length. */ 342 | static void 343 | ctf_str_count_strtab (void *key _libctf_unused_, void *value, 344 | void *arg) 345 | { 346 | ctf_str_atom_t *atom = (ctf_str_atom_t *) value; 347 | ctf_strtab_write_state_t *s = (ctf_strtab_write_state_t *) arg; 348 | 349 | /* We only factor in the length of items that have no offset and have refs: 350 | other items are in the external strtab, or will simply not be written out 351 | at all. They still contribute to the total count, though, because we still 352 | have to sort them. We add in the null string's length explicitly, outside 353 | this function, since it is explicitly written out even if it has no refs at 354 | all. */ 355 | 356 | if (s->nullstr == atom) 357 | { 358 | s->strtab_count++; 359 | return; 360 | } 361 | 362 | if (!ctf_list_empty_p (&atom->csa_refs)) 363 | { 364 | if (!atom->csa_external_offset) 365 | s->strtab->cts_len += strlen (atom->csa_str) + 1; 366 | s->strtab_count++; 367 | } 368 | } 369 | 370 | /* Populate the sorttab with pointers to the strtab atoms. */ 371 | static void 372 | ctf_str_populate_sorttab (void *key _libctf_unused_, void *value, 373 | void *arg) 374 | { 375 | ctf_str_atom_t *atom = (ctf_str_atom_t *) value; 376 | ctf_strtab_write_state_t *s = (ctf_strtab_write_state_t *) arg; 377 | 378 | /* Skip the null string. */ 379 | if (s->nullstr == atom) 380 | return; 381 | 382 | /* Skip atoms with no refs. */ 383 | if (!ctf_list_empty_p (&atom->csa_refs)) 384 | s->sorttab[s->i++] = atom; 385 | } 386 | 387 | /* Sort the strtab. */ 388 | static int 389 | ctf_str_sort_strtab (const void *a, const void *b) 390 | { 391 | ctf_str_atom_t **one = (ctf_str_atom_t **) a; 392 | ctf_str_atom_t **two = (ctf_str_atom_t **) b; 393 | 394 | return (strcmp ((*one)->csa_str, (*two)->csa_str)); 395 | } 396 | 397 | /* Write out and return a strtab containing all strings with recorded refs, 398 | adjusting the refs to refer to the corresponding string. The returned strtab 399 | may be NULL on error. Also populate the synthetic strtab with mappings from 400 | external strtab offsets to names, so we can look them up with ctf_strptr(). 401 | Only external strtab offsets with references are added. */ 402 | ctf_strs_writable_t 403 | ctf_str_write_strtab (ctf_file_t *fp) 404 | { 405 | ctf_strs_writable_t strtab; 406 | ctf_str_atom_t *nullstr; 407 | uint32_t cur_stroff = 0; 408 | ctf_strtab_write_state_t s; 409 | ctf_str_atom_t **sorttab; 410 | size_t i; 411 | int any_external = 0; 412 | 413 | memset (&strtab, 0, sizeof (struct ctf_strs_writable)); 414 | memset (&s, 0, sizeof (struct ctf_strtab_write_state)); 415 | s.strtab = &strtab; 416 | 417 | nullstr = ctf_dynhash_lookup (fp->ctf_str_atoms, ""); 418 | if (!nullstr) 419 | { 420 | ctf_dprintf ("Internal error: null string not found in strtab.\n"); 421 | strtab.cts_strs = NULL; 422 | return strtab; 423 | } 424 | 425 | s.nullstr = nullstr; 426 | ctf_dynhash_iter (fp->ctf_str_atoms, ctf_str_count_strtab, &s); 427 | strtab.cts_len++; /* For the null string. */ 428 | 429 | ctf_dprintf ("%lu bytes of strings in strtab.\n", 430 | (unsigned long) strtab.cts_len); 431 | 432 | /* Sort the strtab. Force the null string to be first. */ 433 | sorttab = calloc (s.strtab_count, sizeof (ctf_str_atom_t *)); 434 | if (!sorttab) 435 | goto oom; 436 | 437 | sorttab[0] = nullstr; 438 | s.i = 1; 439 | s.sorttab = sorttab; 440 | ctf_dynhash_iter (fp->ctf_str_atoms, ctf_str_populate_sorttab, &s); 441 | 442 | qsort (&sorttab[1], s.strtab_count - 1, sizeof (ctf_str_atom_t *), 443 | ctf_str_sort_strtab); 444 | 445 | if ((strtab.cts_strs = malloc (strtab.cts_len)) == NULL) 446 | goto oom_sorttab; 447 | 448 | if (!fp->ctf_syn_ext_strtab) 449 | fp->ctf_syn_ext_strtab = ctf_dynhash_create (ctf_hash_integer, 450 | ctf_hash_eq_integer, 451 | NULL, NULL); 452 | if (!fp->ctf_syn_ext_strtab) 453 | goto oom_strtab; 454 | 455 | /* Update all refs: also update the strtab appropriately. */ 456 | for (i = 0; i < s.strtab_count; i++) 457 | { 458 | if (sorttab[i]->csa_external_offset) 459 | { 460 | /* External strtab entry: populate the synthetic external strtab. 461 | 462 | This is safe because you cannot ctf_rollback to before the point 463 | when a ctf_update is done, and the strtab is written at ctf_update 464 | time. So any atoms we reference here are sure to stick around 465 | until ctf_file_close. */ 466 | 467 | any_external = 1; 468 | ctf_str_update_refs (sorttab[i], sorttab[i]->csa_external_offset); 469 | if (ctf_dynhash_insert (fp->ctf_syn_ext_strtab, 470 | (void *) (uintptr_t) 471 | sorttab[i]->csa_external_offset, 472 | (void *) sorttab[i]->csa_str) < 0) 473 | goto oom_strtab; 474 | sorttab[i]->csa_offset = sorttab[i]->csa_external_offset; 475 | } 476 | else 477 | { 478 | /* Internal strtab entry with refs: actually add to the string 479 | table. */ 480 | 481 | ctf_str_update_refs (sorttab[i], cur_stroff); 482 | sorttab[i]->csa_offset = cur_stroff; 483 | strcpy (&strtab.cts_strs[cur_stroff], sorttab[i]->csa_str); 484 | cur_stroff += strlen (sorttab[i]->csa_str) + 1; 485 | } 486 | } 487 | free (sorttab); 488 | 489 | if (!any_external) 490 | { 491 | ctf_dynhash_destroy (fp->ctf_syn_ext_strtab); 492 | fp->ctf_syn_ext_strtab = NULL; 493 | } 494 | 495 | /* All the provisional strtab entries are now real strtab entries, and 496 | ctf_strptr() will find them there. The provisional offset now starts right 497 | beyond the new end of the strtab. */ 498 | 499 | ctf_dynhash_empty (fp->ctf_prov_strtab); 500 | fp->ctf_str_prov_offset = strtab.cts_len + 1; 501 | return strtab; 502 | 503 | oom_strtab: 504 | free (strtab.cts_strs); 505 | strtab.cts_strs = NULL; 506 | oom_sorttab: 507 | free (sorttab); 508 | oom: 509 | return strtab; 510 | } 511 | -------------------------------------------------------------------------------- /libctf/ctf-subr.c: -------------------------------------------------------------------------------- 1 | /* Simple subrs. 2 | Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. 3 | 4 | Licensed under the Universal Permissive License v 1.0 as shown at 5 | http://oss.oracle.com/licenses/upl. 6 | 7 | Licensed under the GNU General Public License (GPL), version 2. See the file 8 | COPYING in the top level of this tree. */ 9 | 10 | #include 11 | #ifdef HAVE_MMAP 12 | #include 13 | #endif 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | int _libctf_version = CTF_VERSION; /* Library client version. */ 20 | int _libctf_debug = 0; /* Debugging messages enabled. */ 21 | 22 | /* Private, read-only mmap from a file, with fallback to copying. 23 | 24 | No handling of page-offset issues at all: the caller must allow for that. */ 25 | 26 | _libctf_malloc_ void * 27 | ctf_mmap (size_t length, size_t offset, int fd) 28 | { 29 | void *data; 30 | 31 | #ifdef HAVE_MMAP 32 | data = mmap (NULL, length, PROT_READ, MAP_PRIVATE, fd, offset); 33 | if (data == MAP_FAILED) 34 | data = NULL; 35 | #else 36 | if ((data = malloc (length)) != NULL) 37 | { 38 | if (ctf_pread (fd, data, length, offset) <= 0) 39 | { 40 | free (data); 41 | data = NULL; 42 | } 43 | } 44 | #endif 45 | return data; 46 | } 47 | 48 | void 49 | ctf_munmap (void *buf, size_t length _libctf_unused_) 50 | { 51 | #ifdef HAVE_MMAP 52 | (void) munmap (buf, length); 53 | #else 54 | free (buf); 55 | #endif 56 | } 57 | 58 | ssize_t 59 | ctf_pread (int fd, void *buf, ssize_t count, off_t offset) 60 | { 61 | ssize_t len; 62 | size_t acc = 0; 63 | char *data = (char *) buf; 64 | 65 | #ifdef HAVE_PREAD 66 | while (count > 0) 67 | { 68 | errno = 0; 69 | if (((len = pread (fd, data, count, offset)) < 0) && 70 | errno != EINTR) 71 | return len; 72 | if (errno == EINTR) 73 | continue; 74 | 75 | acc += len; 76 | if (len == 0) /* EOF. */ 77 | return acc; 78 | 79 | count -= len; 80 | offset += len; 81 | data += len; 82 | } 83 | return acc; 84 | #else 85 | off_t orig_off; 86 | 87 | if ((orig_off = lseek (fd, 0, SEEK_CUR)) < 0) 88 | return -1; 89 | if ((lseek (fd, offset, SEEK_SET)) < 0) 90 | return -1; 91 | 92 | while (count > 0) 93 | { 94 | errno = 0; 95 | if (((len = read (fd, data, count)) < 0) && 96 | errno != EINTR) 97 | return len; 98 | if (errno == EINTR) 99 | continue; 100 | 101 | acc += len; 102 | if (len == 0) /* EOF. */ 103 | break; 104 | 105 | count -= len; 106 | data += len; 107 | } 108 | if ((lseek (fd, orig_off, SEEK_SET)) < 0) 109 | return -1; /* offset is smashed. */ 110 | #endif 111 | 112 | return acc; 113 | } 114 | 115 | const char * 116 | ctf_strerror (int err) 117 | { 118 | return (const char *) (strerror (err)); 119 | } 120 | 121 | /* Set the CTF library client version to the specified version. If version is 122 | zero, we just return the default library version number. */ 123 | int 124 | ctf_version (int version) 125 | { 126 | if (version < 0) 127 | { 128 | errno = EINVAL; 129 | return -1; 130 | } 131 | 132 | if (version > 0) 133 | { 134 | /* Dynamic version switching is not presently supported. */ 135 | if (version != CTF_VERSION) 136 | { 137 | errno = ENOTSUP; 138 | return -1; 139 | } 140 | ctf_dprintf ("ctf_version: client using version %d\n", version); 141 | _libctf_version = version; 142 | } 143 | 144 | return _libctf_version; 145 | } 146 | 147 | void 148 | libctf_init_debug (void) 149 | { 150 | static int inited; 151 | if (!inited) 152 | { 153 | _libctf_debug = getenv ("LIBCTF_DEBUG") != NULL; 154 | inited = 1; 155 | } 156 | } 157 | 158 | void ctf_setdebug (int debug) 159 | { 160 | /* Ensure that libctf_init_debug() has been called, so that we don't get our 161 | debugging-on-or-off smashed by the next call. */ 162 | 163 | libctf_init_debug(); 164 | _libctf_debug = debug; 165 | ctf_dprintf ("CTF debugging set to %i\n", debug); 166 | } 167 | 168 | int ctf_getdebug (void) 169 | { 170 | return _libctf_debug; 171 | } 172 | 173 | _libctf_printflike_ (1, 2) 174 | void ctf_dprintf (const char *format, ...) 175 | { 176 | if (_libctf_debug) 177 | { 178 | va_list alist; 179 | 180 | va_start (alist, format); 181 | fflush (stdout); 182 | (void) fputs ("libctf DEBUG: ", stderr); 183 | (void) vfprintf (stderr, format, alist); 184 | va_end (alist); 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /libctf/ctf-util.c: -------------------------------------------------------------------------------- 1 | /* Miscellaneous utilities. 2 | Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. 3 | 4 | Licensed under the Universal Permissive License v 1.0 as shown at 5 | http://oss.oracle.com/licenses/upl. 6 | 7 | Licensed under the GNU General Public License (GPL), version 2. See the file 8 | COPYING in the top level of this tree. */ 9 | 10 | #include 11 | #include 12 | 13 | /* Simple doubly-linked list append routine. This implementation assumes that 14 | each list element contains an embedded ctf_list_t as the first member. 15 | An additional ctf_list_t is used to store the head (l_next) and tail 16 | (l_prev) pointers. The current head and tail list elements have their 17 | previous and next pointers set to NULL, respectively. */ 18 | 19 | void 20 | ctf_list_append (ctf_list_t *lp, void *newp) 21 | { 22 | ctf_list_t *p = lp->l_prev; /* p = tail list element. */ 23 | ctf_list_t *q = newp; /* q = new list element. */ 24 | 25 | lp->l_prev = q; 26 | q->l_prev = p; 27 | q->l_next = NULL; 28 | 29 | if (p != NULL) 30 | p->l_next = q; 31 | else 32 | lp->l_next = q; 33 | } 34 | 35 | /* Prepend the specified existing element to the given ctf_list_t. The 36 | existing pointer should be pointing at a struct with embedded ctf_list_t. */ 37 | 38 | void 39 | ctf_list_prepend (ctf_list_t * lp, void *newp) 40 | { 41 | ctf_list_t *p = newp; /* p = new list element. */ 42 | ctf_list_t *q = lp->l_next; /* q = head list element. */ 43 | 44 | lp->l_next = p; 45 | p->l_prev = NULL; 46 | p->l_next = q; 47 | 48 | if (q != NULL) 49 | q->l_prev = p; 50 | else 51 | lp->l_prev = p; 52 | } 53 | 54 | /* Delete the specified existing element from the given ctf_list_t. The 55 | existing pointer should be pointing at a struct with embedded ctf_list_t. */ 56 | 57 | void 58 | ctf_list_delete (ctf_list_t *lp, void *existing) 59 | { 60 | ctf_list_t *p = existing; 61 | 62 | if (p->l_prev != NULL) 63 | p->l_prev->l_next = p->l_next; 64 | else 65 | lp->l_next = p->l_next; 66 | 67 | if (p->l_next != NULL) 68 | p->l_next->l_prev = p->l_prev; 69 | else 70 | lp->l_prev = p->l_prev; 71 | } 72 | 73 | /* Return 1 if the list is empty. */ 74 | 75 | int 76 | ctf_list_empty_p (ctf_list_t *lp) 77 | { 78 | return (lp->l_next == NULL && lp->l_prev == NULL); 79 | } 80 | 81 | /* Convert a 32-bit ELF symbol into Elf64 and return a pointer to it. */ 82 | 83 | Elf64_Sym * 84 | ctf_sym_to_elf64 (const Elf32_Sym *src, Elf64_Sym *dst) 85 | { 86 | dst->st_name = src->st_name; 87 | dst->st_value = src->st_value; 88 | dst->st_size = src->st_size; 89 | dst->st_info = src->st_info; 90 | dst->st_other = src->st_other; 91 | dst->st_shndx = src->st_shndx; 92 | 93 | return dst; 94 | } 95 | 96 | /* A string appender working on dynamic strings. Returns NULL on OOM. */ 97 | 98 | char * 99 | ctf_str_append (char *s, const char *append) 100 | { 101 | size_t s_len = 0; 102 | 103 | if (append == NULL) 104 | return s; 105 | 106 | if (s != NULL) 107 | s_len = strlen (s); 108 | 109 | size_t append_len = strlen (append); 110 | 111 | if ((s = realloc (s, s_len + append_len + 1)) == NULL) 112 | return NULL; 113 | 114 | memcpy (s + s_len, append, append_len); 115 | s[s_len + append_len] = '\0'; 116 | 117 | return s; 118 | } 119 | 120 | /* A version of ctf_str_append that returns the old string on OOM. */ 121 | 122 | char * 123 | ctf_str_append_noerr (char *s, const char *append) 124 | { 125 | char *new_s; 126 | 127 | new_s = ctf_str_append (s, append); 128 | if (!new_s) 129 | return s; 130 | return new_s; 131 | } 132 | 133 | /* A realloc() that fails noisily if called with any ctf_str_num_users. */ 134 | void * 135 | ctf_realloc (ctf_file_t *fp, void *ptr, size_t size) 136 | { 137 | if (fp->ctf_str_num_refs > 0) 138 | { 139 | ctf_dprintf ("%p: attempt to realloc() string table with %lu active refs\n", 140 | (void *) fp, (unsigned long) fp->ctf_str_num_refs); 141 | return NULL; 142 | } 143 | return realloc (ptr, size); 144 | } 145 | 146 | /* Store the specified error code into errp if it is non-NULL, and then 147 | return NULL for the benefit of the caller. */ 148 | 149 | void * 150 | ctf_set_open_errno (int *errp, int error) 151 | { 152 | if (errp != NULL) 153 | *errp = error; 154 | return NULL; 155 | } 156 | 157 | /* Store the specified error code into the CTF container, and then return 158 | CTF_ERR / -1 for the benefit of the caller. */ 159 | 160 | unsigned long 161 | ctf_set_errno (ctf_file_t * fp, int err) 162 | { 163 | fp->ctf_errno = err; 164 | return CTF_ERR; 165 | } 166 | -------------------------------------------------------------------------------- /libctf/libdtrace-ctf.ver: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * Licensed under the Universal Permissive License v 1.0 as shown at 5 | * http://oss.oracle.com/licenses/upl. 6 | * 7 | * Licensed under the GNU General Public License (GPL), version 2. See the file 8 | * COPYING in the top level of this tree. 9 | */ 10 | 11 | LIBDTRACE_CTF_1.0 { 12 | global: 13 | ctf_bufopen; 14 | ctf_fdopen; 15 | ctf_open; 16 | ctf_create; 17 | ctf_close; 18 | 19 | ctf_parent_file; 20 | ctf_parent_name; 21 | ctf_parent_name_set; 22 | 23 | ctf_import; 24 | ctf_setmodel; 25 | ctf_getmodel; 26 | 27 | ctf_setspecific; 28 | ctf_getspecific; 29 | 30 | ctf_errno; 31 | ctf_errmsg; 32 | ctf_version; 33 | 34 | ctf_func_info; 35 | ctf_func_args; 36 | 37 | ctf_lookup_by_name; 38 | ctf_lookup_by_symbol; 39 | ctf_lookup_variable; 40 | 41 | ctf_type_resolve; 42 | ctf_type_lname; 43 | ctf_type_name; 44 | ctf_type_size; 45 | ctf_type_align; 46 | ctf_type_kind; 47 | ctf_type_reference; 48 | ctf_type_pointer; 49 | ctf_type_encoding; 50 | ctf_type_visit; 51 | ctf_type_cmp; 52 | ctf_type_compat; 53 | 54 | ctf_member_info; 55 | ctf_array_info; 56 | 57 | ctf_enum_name; 58 | ctf_enum_value; 59 | 60 | ctf_label_set; 61 | ctf_label_get; 62 | 63 | ctf_label_topmost; 64 | ctf_label_info; 65 | 66 | ctf_member_iter; 67 | ctf_enum_iter; 68 | ctf_type_iter; 69 | ctf_label_iter; 70 | 71 | ctf_add_array; 72 | ctf_add_const; 73 | ctf_add_enum; 74 | ctf_add_float; 75 | ctf_add_forward; 76 | ctf_add_function; 77 | ctf_add_integer; 78 | ctf_add_pointer; 79 | ctf_add_type; 80 | ctf_add_typedef; 81 | ctf_add_restrict; 82 | ctf_add_struct; 83 | ctf_add_union; 84 | ctf_add_volatile; 85 | 86 | ctf_add_enumerator; 87 | ctf_add_member; 88 | ctf_add_member_offset; 89 | ctf_add_variable; 90 | 91 | ctf_set_array; 92 | 93 | ctf_update; 94 | ctf_discard; 95 | ctf_write; 96 | ctf_gzwrite; 97 | local: 98 | *; 99 | }; 100 | 101 | LIBDTRACE_CTF_1.1 { 102 | global: 103 | ctf_variable_iter; 104 | } LIBDTRACE_CTF_1.0; 105 | 106 | LIBDTRACE_CTF_1.2 { 107 | global: 108 | ctf_snapshot; 109 | ctf_rollback; 110 | } LIBDTRACE_CTF_1.1; 111 | 112 | LIBDTRACE_CTF_1.3 { 113 | global: 114 | ctf_compress_write; 115 | ctf_arc_write; 116 | ctf_arc_open; 117 | ctf_arc_close; 118 | ctf_arc_open_by_name; 119 | ctf_archive_iter; 120 | } LIBDTRACE_CTF_1.2; 121 | 122 | LIBDTRACE_CTF_1.4 { 123 | global: 124 | ctf_type_isparent; 125 | ctf_type_ischild; 126 | ctf_getdatasect; 127 | ctf_archive_raw_iter; 128 | } LIBDTRACE_CTF_1.3; 129 | 130 | LIBDTRACE_CTF_1.5 { 131 | global: 132 | ctf_add_struct_sized; 133 | ctf_add_union_sized; 134 | } LIBDTRACE_CTF_1.4; 135 | 136 | LIBDTRACE_CTF_1.6 { 137 | global: 138 | ctf_add_slice; 139 | ctf_add_enum_encoded; 140 | ctf_add_member_encoded; 141 | ctf_type_aname; 142 | ctf_dump; 143 | ctf_simple_open; 144 | ctf_bfdopen; 145 | ctf_setdebug; 146 | ctf_getdebug; 147 | ctf_file_close; 148 | ctf_get_arc; 149 | ctf_arc_bufopen; 150 | ctf_arc_open_by_name_sections; 151 | ctf_bfdopen_ctfsect; 152 | ctf_cuname; 153 | ctf_cuname_set; 154 | ctf_arc_write_fd; 155 | ctf_write_mem; 156 | ctf_link_add_ctf; 157 | ctf_link_add_cu_mapping; 158 | ctf_link; 159 | ctf_link_add_strtab; 160 | ctf_link_shuffle_syms; 161 | ctf_link_write; 162 | ctf_type_iter_all; 163 | ctf_func_type_info; 164 | ctf_func_type_args; 165 | ctf_type_aname_raw; 166 | } LIBDTRACE_CTF_1.5; 167 | -------------------------------------------------------------------------------- /libctf/swap.h: -------------------------------------------------------------------------------- 1 | /* Byte-swapping wrapper. 2 | Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved. 3 | 4 | Licensed under the Universal Permissive License v 1.0 as shown at 5 | http://oss.oracle.com/licenses/upl. 6 | 7 | Licensed under the GNU General Public License (GPL), version 2. See the file 8 | COPYING in the top level of this tree. 9 | 10 | Not synced with GNU. */ 11 | 12 | #ifndef _CTF_SWAP_H 13 | #define _CTF_SWAP_H 14 | 15 | #include "config.h" 16 | #include 17 | 18 | #ifdef HAVE_BYTESWAP_H 19 | #include 20 | #else 21 | #error is required. 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /libdtrace-ctf.spec: -------------------------------------------------------------------------------- 1 | # spec file for package libdtrace-ctf 2 | # 3 | # Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Universal Permissive License v 1.0 as shown at 6 | # http://oss.oracle.com/licenses/upl. 7 | # 8 | # Licensed under the GNU General Public License (GPL), version 2. See the file 9 | # COPYING in the top level of this tree. 10 | 11 | BuildRequires: rpm 12 | Name: libdtrace-ctf 13 | License: GPLv2 14 | Group: Development/Libraries 15 | Requires: gcc binutils zlib glib2 16 | BuildRequires: binutils-devel kernel-headers glibc-headers glib2-devel zlib-devel 17 | Summary: Compact Type Format library. 18 | Version: 1.2.0 19 | Release: 0.2%{?dist} 20 | Source: libdtrace-ctf-%{version}.tar.bz2 21 | BuildRoot: %{_tmppath}/%{name}-%{version}-build 22 | ExclusiveArch: x86_64 sparc64 aarch64 23 | 24 | %description 25 | The Compact Type Format library provides a C-level representation of 26 | a subset of the C type system. 27 | 28 | Maintainers: 29 | ----------- 30 | DTrace external development mailing list 31 | 32 | %package devel 33 | Summary: Compact Type Format development headers. 34 | Requires: %{name}%{?_isa} = %{version}-%{release} 35 | Requires: zlib-devel 36 | 37 | %description devel 38 | Headers and libraries to develop applications using the Compact Type Format. 39 | 40 | %prep 41 | %setup -q 42 | 43 | %build 44 | make -j $(getconf _NPROCESSORS_ONLN) VERSION=%{version} optdebugging=yes 45 | 46 | %install 47 | echo rm -rf $RPM_BUILD_ROOT 48 | mkdir -p $RPM_BUILD_ROOT/usr/sbin 49 | make DESTDIR=$RPM_BUILD_ROOT VERSION=%{version} install 50 | 51 | %clean 52 | [ "$RPM_BUILD_ROOT" != "/" ] && rm -rf "$RPM_BUILD_ROOT" 53 | rm -rf $RPM_BUILD_DIR/%{name}-%{version} 54 | 55 | %post 56 | /sbin/ldconfig 57 | 58 | %postun 59 | /sbin/ldconfig 60 | 61 | %files 62 | %defattr(-,root,root,755) 63 | %exclude /usr/src/debug 64 | %exclude /usr/lib/debug 65 | %{_libdir}/libdtrace-ctf.so.* 66 | %{_includedir}/sys/ctf_types.h 67 | 68 | %files devel 69 | %defattr(-,root,root,-) 70 | %{_bindir}/ctf_dump 71 | %{_bindir}/ctf_ar 72 | %defattr(-,root,root,755) 73 | %exclude /usr/src/debug 74 | %exclude /usr/lib/debug 75 | %{_libdir}/libdtrace-ctf.so 76 | %{_includedir}/sys/ctf.h 77 | %{_includedir}/sys/ctf_api.h 78 | 79 | %changelog 80 | * Wed Aug 7 2019 - nick.alcock@oracle.com - 1.2.0-0.2 81 | - Work towards 1.2.0. 82 | - Reformat everything to GNU style. 83 | - Support opening CTF files of any endianness. 84 | - Transparent upgrading now supports changes to the header layout. 85 | - Use GHashTable for dynamically-sized hashtables. 86 | - ctf_fdopen and ctf_open now work, take a BFD target, 87 | and return a ctf_archive_t containing at least one member. 88 | - Many new API functions: see NEWS. 89 | - Improvements to ctf_add_type. 90 | - New string table management machinery, supporting external string tables. 91 | - ctf_update calls are no longer required when updating ctf_file_t's. 92 | - Dumper machinery rewritten as a library function, ctf_dump(). 93 | - Support for non-ELF platforms, and platforms not supporting pread() 94 | or mmap(). 95 | - New linker infrastructure, ctf_link_*(). Very new, improvement likely. 96 | 97 | * Fri Dec 14 2018 - nick.alcock@oracle.com - 1.1.0-1 98 | - Add ctf_add_{struct,union}_sized(). [Orabug: 29054972] 99 | - Work around some very minor CTF-generation bugs seen in the wild 100 | in old UEK kernels. [Orabug: 28952429] 101 | - Do not mprotect() the heap by mistake when reading CTF from a 102 | user-provided buffer. [Orabug: 28952429] 103 | * Thu Nov 22 2018 - nick.alcock@oracle.com - 1.0.1-0.2 104 | - Work around some CTF-generation bugs, narrower hack. 105 | * Wed Oct 24 2018 - nick.alcock@oracle.com - 1.0.0-1 106 | - Format v2, supporting many more types and enum/struct/union members. 107 | v1 CTF files are transparently updated to v2. No soname change, but 108 | some API for users directly accessing CTF files is broken. 109 | [Orabug: 28150489] 110 | * Fri May 04 2018 - nick.alcock@oracle.com - 0.8.1-1 111 | - Fix ctf_rollback() in client containers to delete only the types 112 | added since the last snapshot, rather than all of them. 113 | [Orabug: 27971037] 114 | * Mon Jan 29 2018 - nick.alcock@oracle.com - 0.8.0-1 115 | - Add CTF_CHAR. 116 | * Mon Jan 22 2018 - nick.alcock@oracle.com - 0.7.1-1 117 | - Fix CTF archive alignment and failed write() handling 118 | (Tomas Jedlicka) [Orabug: 27191792, 27204447] 119 | - Build on arm64 (Vincent Lim) [Orabug: 27418554] 120 | * Tue Sep 12 2017 - nick.alcock@oracle.com - 0.7.0-1 121 | - CTF archive support [Orabug: 25815388] 122 | * Tue May 23 2017 - nick.alcock@oracle.com - 0.6.0-1 123 | - Bitfield support (Robert M. Harris) [Orabug: 25815088] 124 | * Fri Aug 14 2015 - nick.alcock@oracle.com - 0.5.0-3 125 | - Include the distribution in the RPM release. [Orabug: 21211461] 126 | - No longer Provide: our own name. [Orabug: 21622263] 127 | * Thu Apr 23 2015 - nick.alcock%oracle.com - 0.5.0-2 128 | - libdtrace-ctf-devel now depends on the appropriate version of libdtrace-ctf. 129 | [Orabug: 20948460] 130 | * Fri Mar 20 2015 - nick.alcock@oracle.com - 0.5.0 131 | - SPARC / big-endian support. [Orabug: 20762799] 132 | * Tue Mar 17 2015 - nick.alcock@oracle.com - 0.4.3 133 | - New ctf_snapshot() and ctf_rollback() functions. [Orabug: 20229533] 134 | * Mon Oct 13 2014 - nick.alcock@oracle.com - 0.4.2 135 | - Work with GNU Make 4.0. 136 | * Tue Dec 17 2013 - nick.alcock@oracle.com - 0.4.1 137 | - Improvements to ctf_dump. 138 | - No longer look off the end of strings when looking up types by name. 139 | * Tue Jul 23 2013 - nick.alcock@oracle.com - 0.4.0 140 | - New ctf_dump tool and ctf_variable_iter() iteration function. 141 | * Wed Nov 28 2012 - kris.van.hees@oracle.com - 0.3.3 142 | - Report errors on type lookup correctly. 143 | * Fri Nov 2 2012 - nick.alcock@oracle.com - 0.3.2 144 | - CTF sections renamed to .ctf. 145 | * Thu Aug 30 2012 - nick.alcock@oracle.com - 0.3.0 146 | - Split off from dtrace. 147 | -------------------------------------------------------------------------------- /maint/.last-sync.binutils-gdb: -------------------------------------------------------------------------------- 1 | f3772ff215a62285a4ff94d813085daabdd3f216 2 | -------------------------------------------------------------------------------- /maint/Makefile.maint: -------------------------------------------------------------------------------- 1 | 2 | .PHONY: all gnu dir include src _subst __one_subst 3 | .SILENT: 4 | 5 | SHELL=/bin/bash 6 | OUTFILE=$(FILE) 7 | FORCE= 8 | 9 | topdir := $(shell pwd) 10 | 11 | all: 12 | echo 'Targets:' >&2 13 | printf '\tgnu GNU_DIR=/cyg/tree/root [FORCE=t] \n' >&2 14 | printf '\tgnu-warnings\n' >&2 15 | 16 | HEADERS := include/sys/ctf.h include/sys/ctf-api.h 17 | 18 | gnu: dir include src 19 | git show-ref --verify -s --head HEAD > $(topdir)/maint/.last-sync.$(notdir $(GNU_DIR)) 20 | 21 | gnu-warnings: 22 | $(MAKE) clean 23 | $(MAKE) CFLAGS="-O2 -g -Wall -W -Wall -Wno-narrowing -Wwrite-strings -Wmissing-format-attribute -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -pedantic -Wno-long-long" 24 | 25 | dir: 26 | [[ -n "$(GNU_DIR)" ]] || { echo "Please set GNU_DIR." >&2 && false; } 27 | [[ -f $(GNU_DIR)/Makefile.tpl ]] || \ 28 | { echo "Please set GNU_DIR to the top level of a Cygnus tree." >&2; \ 29 | false; } 30 | 31 | include: 32 | for name in $(HEADERS); do \ 33 | $(MAKE) -f $(topdir)/maint/Makefile.maint _subst topdir=$(topdir) \ 34 | FILE=$$name OUTFILE=$$(printf "%s" "$$name" | sed 's,sys/ctf,ctf,'); \ 35 | done 36 | 37 | src: 38 | for name in libctf/*.c libctf/*.h; do \ 39 | head -50 $$name | grep -q 'Not synced with GNU.' || \ 40 | $(MAKE) -f $(topdir)/maint/Makefile.maint _subst topdir=$(topdir) \ 41 | FILE=$$name; \ 42 | done 43 | 44 | _subst: 45 | if [[ -f $(topdir)/maint/.last-sync.$(notdir $(GNU_DIR)) ]]; then \ 46 | { git show $(shell cat $(topdir)/maint/.last-sync.$(notdir $(GNU_DIR)) 2>/dev/null):$(FILE) | \ 47 | $(MAKE) -f $(topdir)/maint/Makefile.maint __one_subst \ 48 | topdir=$(topdir) OUT=$(topdir)/maint/.old; } || \ 49 | cat /dev/null > $(topdir)/maint/.old; \ 50 | fi 51 | 52 | mkdir -p $(GNU_DIR)/$(dir $(OUTFILE)) 53 | if [[ -z $FORCE ]] && [[ -e $(topdir)/maint/.old ]] && [[ -e $(GNU_DIR)/$(OUTFILE) ]] && \ 54 | ! cmp -s $(topdir)/maint/.old $(GNU_DIR)/$(OUTFILE); then \ 55 | echo "WARNING: $(GNU_DIR)/$(OUTFILE): changed in GNU tree, needs manual sync" >&2; \ 56 | diff -u $(topdir)/maint/.old $(GNU_DIR)/$(OUTFILE); \ 57 | else \ 58 | cat $(FILE) | $(MAKE) -f $(topdir)/maint/Makefile.maint \ 59 | __one_subst topdir=$(topdir) OUT=$(GNU_DIR)/$(OUTFILE); \ 60 | fi 61 | rm -f $(topdir)/maint/.old 62 | printf "SYNC %s\n" "$(FILE)" 63 | 64 | __one_subst: 65 | awk -f $(topdir)/maint/comment-change.awk -v topdir=$(topdir) | \ 66 | sed 's, $(OUT) 67 | unifdef -x 2 -m -UNO_COMPAT -DBFD_ONLY $(OUT) 68 | -------------------------------------------------------------------------------- /maint/comment-change.awk: -------------------------------------------------------------------------------- 1 | function readfile(file, tmp, save_rs) 2 | { 3 | save_rs = RS 4 | RS = "^$" 5 | getline tmp < file 6 | close(file) 7 | RS = save_rs 8 | 9 | return tmp 10 | } 11 | 12 | BEGIN { 13 | found = 0; 14 | header = readfile(topdir "/maint/header") 15 | } 16 | 17 | !found && /\*\// { 18 | printf(" Copyright (C) 2019 Free Software Foundation, Inc.\n\n"); 19 | 20 | printf ("%s", header) 21 | found = 1 22 | } 23 | 24 | !found && /Copyright \(c\)/,/\*\// { 25 | next 26 | } 27 | 28 | { print } 29 | -------------------------------------------------------------------------------- /maint/header: -------------------------------------------------------------------------------- 1 | This file is part of libctf. 2 | 3 | libctf is free software; you can redistribute it and/or modify it under 4 | the terms of the GNU General Public License as published by the Free 5 | Software Foundation; either version 3, or (at your option) any later 6 | version. 7 | 8 | This program is distributed in the hope that it will be useful, but 9 | WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 | See the GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; see the file COPYING. If not see 15 | . */ 16 | -------------------------------------------------------------------------------- /tools/Build: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. 2 | # 3 | # Licensed under the Universal Permissive License v 1.0 as shown at 4 | # http://oss.oracle.com/licenses/upl. 5 | # 6 | # Licensed under the GNU General Public License (GPL), version 2. See the file 7 | # COPYING in the top level of this tree. 8 | 9 | CMDS += ctf_dump ctf_ar 10 | CPPFLAGS += -Ilibctf 11 | 12 | ctf_dump_TARGET = ctf_dump 13 | ctf_dump_DIR := $(current-dir) 14 | ctf_dump_SOURCES = ctf_dump.c 15 | ctf_dump_DEPS = libdtrace-ctf.so 16 | ctf_dump_LIBS = -L$(objdir) -ldtrace-ctf -lz 17 | 18 | ctf_ar_TARGET = ctf_ar 19 | ctf_ar_DIR := $(current-dir) 20 | ctf_ar_SOURCES = car.c 21 | ctf_ar_DEPS = libdtrace-ctf.so 22 | ctf_ar_LIBS = -L$(objdir) -ldtrace-ctf 23 | 24 | # This project is also included in dtrace as a submodule, to assist in 25 | # test coverage analysis and debugging as part of dtrace. We don't want 26 | # to install it in that situation. 27 | ifeq ($(PROJECT),libdtrace-ctf) 28 | install:: 29 | mkdir -p $(BINDIR) 30 | $(call describe-install-target,$(BINDIR),ctf_dump) 31 | install -m 755 $(objdir)/ctf_dump $(BINDIR) 32 | $(call describe-install-target,$(BINDIR),ctf_ar) 33 | install -m 755 $(objdir)/ctf_ar $(BINDIR) 34 | endif 35 | -------------------------------------------------------------------------------- /tools/car.c: -------------------------------------------------------------------------------- 1 | /* CTF archiver. 2 | 3 | Only extraction for now. 4 | 5 | Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 6 | 7 | Licensed under the Universal Permissive License v 1.0 as shown at 8 | http://oss.oracle.com/licenses/upl. 9 | 10 | Licensed under the GNU General Public License (GPL), version 2. */ 11 | 12 | #define _GNU_SOURCE 1 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | 25 | static void 26 | usage (int argc _libctf_unused_, char *argv[]) 27 | { 28 | fprintf (stderr, "Syntax: %s {-x|-t} [-vu] -i parent-ctf] " 29 | "archive...\n\n", argv[0]); 30 | fprintf (stderr, "-x: Extract archive contents.\n"); 31 | fprintf (stderr, "-t: List archive contents without extraction " 32 | "(default).\n"); 33 | fprintf (stderr, "-u: Upgrade the archive to the latest version while " 34 | "extracting.\n"); 35 | fprintf (stderr, "-v: List archive contents while extracting.\n"); 36 | } 37 | 38 | static int extraction = 0; 39 | static int listing_explicit = 0; 40 | static int quiet = 0; 41 | static int upgrade = 0; 42 | 43 | struct visit_data 44 | { 45 | const char *name; 46 | ctf_file_t *fp; 47 | int printed_header; 48 | size_t colsize; 49 | }; 50 | 51 | /* 52 | * Compute the size of column needed to print the names of all archive members. 53 | */ 54 | static int 55 | compute_colsize (ctf_file_t *fp _libctf_unused_, const char *name, void *data) 56 | { 57 | struct visit_data *d = data; 58 | 59 | if ((name != NULL) && (strlen (name) > d->colsize)) 60 | d->colsize = strlen (name); 61 | 62 | return (0); 63 | } 64 | 65 | const char * 66 | ctf_strraw (ctf_file_t *fp, uint32_t name) 67 | { 68 | ctf_strs_t *ctsp = &fp->ctf_str[CTF_NAME_STID (name)]; 69 | 70 | if (ctsp->cts_strs != NULL && CTF_NAME_OFFSET (name) < ctsp->cts_len) 71 | return (ctsp->cts_strs + CTF_NAME_OFFSET (name)); 72 | 73 | /* String table not loaded or corrupt offset. */ 74 | return (NULL); 75 | } 76 | 77 | const char * 78 | ctf_strptr (ctf_file_t *fp, uint32_t name) 79 | { 80 | const char *s = ctf_strraw (fp, name); 81 | return (s != NULL ? s : "(?)"); 82 | } 83 | 84 | static int 85 | print_extract_ctf (ctf_file_t* fp, const char *name, void *data) 86 | { 87 | struct visit_data *d = data; 88 | 89 | if (!quiet) 90 | { 91 | if (!d->printed_header) 92 | { 93 | printf ("\n%s:\n\n", d->name); 94 | printf ("%-*s %-10s %-8s %-8s\n\n", 95 | (int) d->colsize, "Name", "Size", "Types", "Vars"); 96 | d->printed_header = 1; 97 | } 98 | printf ("%-*s %-10zi %-8zi %-8zi\n", (int) d->colsize, name, 99 | fp->ctf_size, fp->ctf_typemax, fp->ctf_nvars); 100 | } 101 | 102 | if (extraction && upgrade) 103 | { 104 | char fn[PATH_MAX]; 105 | int fd; 106 | 107 | snprintf (fn, sizeof (fn), "%s.ctf", name); 108 | if ((fd = open (fn, O_WRONLY | O_CREAT | O_TRUNC | 109 | O_CLOEXEC, 0666)) < 0) 110 | { 111 | fprintf (stderr, "Cannot open %s: %s\n", fn, strerror (errno)); 112 | exit (1); 113 | } 114 | if (ctf_compress_write (fp, fd) < 0) 115 | { 116 | fprintf (stderr, "Cannot write to %s: %s\n", 117 | fn, ctf_errmsg (ctf_errno (fp))); 118 | exit (1); 119 | } 120 | close (fd); 121 | } 122 | return (0); 123 | } 124 | 125 | static int 126 | extract_raw_ctf (const char *name, const void *content, size_t size, 127 | void *unused _libctf_unused_) 128 | { 129 | char fn[PATH_MAX]; 130 | const unsigned char *buf = (const unsigned char *) content; 131 | ssize_t len; 132 | int fd; 133 | 134 | snprintf (fn, sizeof (fn), "%s.ctf", name); 135 | if ((fd = open (fn, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0666)) < 0) 136 | { 137 | fprintf (stderr, "Cannot open %s: %s\n", fn, strerror (errno)); 138 | exit (1); 139 | } 140 | 141 | while (size != 0) 142 | { 143 | if ((len = write (fd, buf, size)) < 0) 144 | { 145 | fprintf (stderr, "Cannot write to %s: %s\n", fn, strerror (errno)); 146 | close (fd); 147 | exit (1); 148 | } 149 | size -= len; 150 | buf += len; 151 | } 152 | close (fd); 153 | return (0); 154 | } 155 | 156 | int 157 | main (int argc, char *argv[]) 158 | { 159 | char **name; 160 | int opt; 161 | 162 | while ((opt = getopt (argc, argv, "hxtuvi:")) != -1) 163 | { 164 | switch (opt) 165 | { 166 | case 'h': 167 | usage (argc, argv); 168 | exit (1); 169 | case 'x': 170 | if (listing_explicit) 171 | { 172 | fprintf (stderr, "Cannot specify both -x and -t.\n"); 173 | exit (1); 174 | } 175 | extraction = 1; 176 | quiet = 1; 177 | break; 178 | case 't': 179 | if (extraction) 180 | { 181 | fprintf (stderr, "Cannot specify both -x and -t.\n"); 182 | exit (1); 183 | } 184 | listing_explicit = 1; 185 | break; 186 | case 'v': 187 | quiet = 0; 188 | break; 189 | case 'u': 190 | upgrade = 1; 191 | break; 192 | } 193 | } 194 | 195 | for (name = &argv[optind]; *name; name++) 196 | { 197 | int err; 198 | ctf_archive_t *arc; 199 | struct visit_data visit_data; 200 | 201 | memset (&visit_data, 0, sizeof (struct visit_data)); 202 | visit_data.name = *name; 203 | visit_data.colsize = 0; 204 | 205 | arc = ctf_arc_open (*name, &err); 206 | if (!arc) 207 | { 208 | fprintf (stderr, "Cannot open %s: %s\n", *name, ctf_errmsg (err)); 209 | continue; 210 | } 211 | if (!quiet 212 | && (err = ctf_archive_iter (arc, compute_colsize, &visit_data)) < 0) 213 | { 214 | fprintf (stderr, "Error reading archive %s for colsize " 215 | "computation: %s\n", *name, ctf_errmsg (err)); 216 | exit (1); 217 | } 218 | visit_data.colsize += 2; 219 | 220 | if ((!quiet || upgrade) 221 | && (err = ctf_archive_iter (arc, print_extract_ctf, &visit_data)) < 0) 222 | { 223 | fprintf (stderr, "Error reading archive %s: %s\n", *name, 224 | ctf_errmsg (err)); 225 | exit (1); 226 | } 227 | if (extraction && !upgrade 228 | && (err = ctf_archive_raw_iter (arc, extract_raw_ctf, &visit_data)) < 0) 229 | { 230 | fprintf (stderr, "Error reading archive %s: %s\n", *name, 231 | ctf_errmsg (err)); 232 | exit (1); 233 | } 234 | ctf_arc_close (arc); 235 | } 236 | 237 | return 0; 238 | } 239 | -------------------------------------------------------------------------------- /tools/ctf_dump.c: -------------------------------------------------------------------------------- 1 | /* A simple CTF dumper. 2 | 3 | Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. 4 | 5 | Licensed under the Universal Permissive License v 1.0 as shown at 6 | http://oss.oracle.com/licenses/upl. 7 | 8 | Licensed under the GNU General Public License (GPL), version 2. See the file 9 | COPYING in the top level of this tree. */ 10 | 11 | #define _GNU_SOURCE 1 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #define GZCHUNKSIZE (1024*512) /* gzip uncompression chunk size. */ 21 | 22 | static ctf_sect_t 23 | ctf_uncompress (const char *name) 24 | { 25 | gzFile f; 26 | size_t chunklen; 27 | char buf[8192]; 28 | const char *errstr; 29 | int err; 30 | 31 | size_t len = 0; 32 | char *result = NULL; 33 | ctf_sect_t sect = { 0 }; 34 | 35 | f = gzopen (name, "r"); 36 | if (!f) 37 | return sect; 38 | 39 | while ((chunklen = gzread (f, buf, 8192)) > 0) 40 | { 41 | result = realloc (result, len + chunklen); 42 | if (result == NULL) 43 | { 44 | fprintf (stderr, "Cannot reallocate: OOM\n"); 45 | exit (1); 46 | } 47 | memcpy (result + len, buf, chunklen); 48 | len += chunklen; 49 | } 50 | 51 | errstr = gzerror (f, &err); 52 | if ((err != Z_OK) && (err != Z_STREAM_END)) 53 | { 54 | fprintf (stderr, "zlib error: %s\n", errstr); 55 | exit (2); 56 | } 57 | 58 | gzclose (f); 59 | 60 | sect.cts_data = result; 61 | sect.cts_size = len; 62 | 63 | return sect; 64 | } 65 | 66 | static ctf_file_t * 67 | read_ctf (const char *file) 68 | { 69 | ctf_sect_t sect = ctf_uncompress (file); 70 | ctf_file_t *ctfp; 71 | int err = 0; 72 | 73 | if (sect.cts_data == NULL) 74 | { 75 | fprintf (stderr, "%s open failure\n", file); 76 | exit (1); 77 | } 78 | 79 | /* Skip 'CTF' files with no CTF data in them (there to placate the 80 | kernel's build system). */ 81 | 82 | if ((sect.cts_size == 0) || (sect.cts_size == 1)) 83 | return (NULL); 84 | 85 | ctfp = ctf_bufopen (§, NULL, NULL, &err); 86 | 87 | if (err != 0) 88 | { 89 | fprintf (stderr, "%s bufopen failure: %s\n", file, ctf_errmsg (err)); 90 | exit (1); 91 | } 92 | 93 | return (ctfp); 94 | } 95 | 96 | static char *indent_lines (ctf_sect_names_t sect _libctf_unused_, 97 | char *line, void *arg) 98 | { 99 | char *spaces = arg; 100 | char *new_str; 101 | 102 | if (asprintf (&new_str, "%s%s", spaces, line) < 0) 103 | return line; 104 | return new_str; 105 | } 106 | 107 | static void 108 | dump_ctf (const char *file, ctf_file_t *fp, int quiet, const char *one_section) 109 | { 110 | const char *things[] = {"Header", "Labels", "Data objects", "Function objects", 111 | "Variables", "Types", "Strings", ""}; 112 | int i; 113 | const char **thing; 114 | 115 | if (!quiet) 116 | printf ("\nCTF file: %s\n", file); 117 | 118 | for (i = 0, thing = things; *thing[0] ; thing++, i++) 119 | { 120 | ctf_dump_state_t *s = NULL; 121 | char *item; 122 | 123 | if (one_section && strcmp (one_section, *thing) != 0) 124 | continue; 125 | 126 | /* Only dump the header if explicitly requested. */ 127 | if (!one_section && strcmp (*thing, "Header") == 0) 128 | continue; 129 | 130 | printf ("\n %s:\n", *thing); 131 | while ((item = ctf_dump (fp, &s, i, indent_lines, 132 | (void *) " ")) != NULL) 133 | { 134 | printf ("%s\n", item); 135 | free (item); 136 | } 137 | 138 | if (ctf_errno (fp)) 139 | goto err; 140 | } 141 | 142 | return; 143 | 144 | err: 145 | fflush (stdout); 146 | fprintf (stderr, "%s %s iteration failed: %s\n", file, *thing, 147 | ctf_errmsg (ctf_errno (fp))); 148 | exit (1); 149 | } 150 | 151 | static void 152 | usage (int argc _libctf_unused_, char *argv[]) 153 | { 154 | fprintf (stderr, "Syntax: %s [-p parent-ctf] [-s section] q -n ctf...\n\n", argv[0]); 155 | fprintf (stderr, "-n: Do not dump parent's contents after loading.\n\n"); 156 | fprintf (stderr, "-q: Quiet: do not dump the CTF filename.\n\n"); 157 | fprintf (stderr, "-p is mandatory if any CTF files have parents.\n"); 158 | fprintf (stderr, "If any CTF file has parents, all CTF files must have " 159 | "the same parent.\n"); 160 | fprintf (stderr, "-s NAME: only dump one section (names are the same as in the full output\n"); 161 | fprintf (stderr, " e.g. \"Types\" or \"Data objects\".\n"); 162 | } 163 | 164 | int 165 | main (int argc, char *argv[]) 166 | { 167 | const char *parent = NULL; 168 | const char *one_section = NULL; 169 | ctf_file_t *pfp = NULL; 170 | int opt; 171 | int skip_parent = 0; 172 | int quiet = 0; 173 | 174 | while ((opt = getopt (argc, argv, "hnqp:s:")) != -1) 175 | { 176 | switch (opt) 177 | { 178 | case 'h': 179 | usage (argc, argv); 180 | exit (1); 181 | case 'p': 182 | parent = optarg; 183 | pfp = read_ctf (parent); 184 | break; 185 | case 's': 186 | one_section = optarg; 187 | break; 188 | case 'q': 189 | quiet = 1; 190 | break; 191 | case 'n': 192 | skip_parent = 1; 193 | break; 194 | } 195 | } 196 | 197 | char **name; 198 | 199 | if (pfp && !skip_parent) 200 | dump_ctf (parent, pfp, quiet, one_section); 201 | 202 | for (name = &argv[optind]; *name; name++) 203 | { 204 | ctf_file_t *fp = read_ctf (*name); 205 | ctf_sect_t sect; 206 | 207 | if (!fp) 208 | continue; 209 | 210 | if (parent) 211 | ctf_import (fp, pfp); 212 | 213 | dump_ctf (*name, fp, quiet, one_section); 214 | 215 | sect = ctf_getdatasect (fp); 216 | ctf_close (fp); 217 | free ((void *) sect.cts_data); 218 | } 219 | 220 | if (pfp) 221 | { 222 | ctf_sect_t sect; 223 | sect = ctf_getdatasect (pfp); 224 | ctf_close (pfp); 225 | free ((void *) sect.cts_data); 226 | } 227 | 228 | return 0; 229 | } 230 | --------------------------------------------------------------------------------