From patchwork Wed Apr 17 20:20:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nick Alcock X-Patchwork-Id: 88602 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id ACEB13846426 for ; Wed, 17 Apr 2024 20:24:14 +0000 (GMT) X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mx0a-00069f02.pphosted.com (mx0a-00069f02.pphosted.com [205.220.165.32]) by sourceware.org (Postfix) with ESMTPS id D4B083858C60 for ; Wed, 17 Apr 2024 20:21:25 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D4B083858C60 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=oracle.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=oracle.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org D4B083858C60 Authentication-Results: server2.sourceware.org; arc=pass smtp.remote-ip=205.220.165.32 ARC-Seal: i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1713385294; cv=pass; b=dOJvFEWwwgq8f9/BEzVA8vKU1TmSB8hdXteh0zp4A6UPus9+rEx1ZsJoRQyeQYH8Gibw2NEL0QpKBMU2yCZkeuR5igaW8gK6uKCX3CtwTCluPjK4Jx9YkPwaLR/9axol2NmKReXkwvUkq1VUazHZuIQ88fapdkazjTo2mVzpwbQ= ARC-Message-Signature: i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1713385294; c=relaxed/simple; bh=9VPmRhQsfVxsj2ji7aKL27ktEMTCf45guTkO/MXOXoU=; h=DKIM-Signature:DKIM-Signature:From:To:Subject:Date:Message-ID: MIME-Version; b=O7FsNUUIq8IGWr2HyxdJN8XdjvqCTQH/IepIqWtRQMBBZWSw0KSiqdZjKXtZhlbPcK6cTctP9EZFDNbQFBX/CZxMvknfP7V6Pb+7fTXC5Cl3b7aaGAZ4S1IEMxdjnsWK2gp1HitB8uC4ir2sP/JkuYCtkwpNVocLUDpuHW2dLuc= ARC-Authentication-Results: i=2; server2.sourceware.org Received: from pps.filterd (m0333521.ppops.net [127.0.0.1]) by mx0b-00069f02.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 43HHiVRb011076 for ; Wed, 17 Apr 2024 20:21:25 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=from : to : subject : date : message-id : in-reply-to : references : content-transfer-encoding : content-type : mime-version; s=corp-2023-11-20; bh=B9eLiHX74bWzFmxZSby1pQPsglAyggQsU96uOm/DvWc=; b=Mir/9ZLC4nHl4XmW23hRyZor/0XJN0lARBhcZfIlH4m7FlzJUjqNr110Xi+JOs7m3QDn JDBq9F6IepSOH9f7B2YW3H1zZHDro0YT89yvIXDNKLleBj0MTnk5S/pvBIomI6whFWvc hz3B3GPBlKsSA0qPSW4htsF6aZDCP99rHaZrwRyxRi5tP/NmUL5skLZtYgcF5Oh/sv9t hMkWeCIZIasCpzNbZ4usBc+W1aAElYzQke3+yJ+A6Cwk7IJgPxUXp/x0NlpcpgOyK0O0 5zkj6dKptc60Ns6Q6PghMPNKLkz6BS7ap6ZS9tRBiTEc1uLD3FowMKLWXSV5B3OFNdln vQ== Received: from phxpaimrmta02.imrmtpd1.prodappphxaev1.oraclevcn.com (phxpaimrmta02.appoci.oracle.com [147.154.114.232]) by mx0b-00069f02.pphosted.com (PPS) with ESMTPS id 3xfgycrvbc-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Wed, 17 Apr 2024 20:21:24 +0000 Received: from pps.filterd (phxpaimrmta02.imrmtpd1.prodappphxaev1.oraclevcn.com [127.0.0.1]) by phxpaimrmta02.imrmtpd1.prodappphxaev1.oraclevcn.com (8.17.1.19/8.17.1.19) with ESMTP id 43HKDNcW029278 for ; Wed, 17 Apr 2024 20:21:24 GMT Received: from nam02-dm3-obe.outbound.protection.outlook.com (mail-dm3nam02lp2040.outbound.protection.outlook.com [104.47.56.40]) by phxpaimrmta02.imrmtpd1.prodappphxaev1.oraclevcn.com (PPS) with ESMTPS id 3xfgg9cr86-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Wed, 17 Apr 2024 20:21:23 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Z/EysDTpfdHlYoudxBLU3Bd2qzPpUOWTRX+3nOgqJZo+81QAqCikdRLodopwyz2mN3TdIxboAL6jhgK8CfeHI8CP/nttlFRamtkktNZqT9DQv0whMRsbixUhgw//U1Rk59r0jkwUhMhYNrQ99hbkRytV31aCFAAR5pPTx2oXTiMxCP4hCeafGfp0tIeiGTtC/5nnKuxAfaVpdnDgP+4f7O804MD5imIC14JBJV8OWmL4oRbqMGEnfeR8DjYQYq5uSproUc11wlFC/1rrdHmLjqqp+pA/cWXBaBqnho6ygOZs7v6l+Rjx7dCJ+GJyXOtMJrKQQ8EITE3r9hXU/Cl0GQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=B9eLiHX74bWzFmxZSby1pQPsglAyggQsU96uOm/DvWc=; b=Z8x+WdH83ehxu9EfBDZZeCPNUewwcY7LAd+zn9LIJSw/+ZmoxycpnwOASJHfFvmDC8/t3SEBCynV7roQZH29fUmCmaOp1b0C/pjWzee5jbZHxhwscUbD4uqPlaOWSvJl876TOEERzf6/NCvUyBUafE3mQaYB9AeAf01RYu7IygpRkkTdKnXktmDK+brvQF22WOLUWxT31aUTVcmS5IKA+xVytg1Y2bCpoQti5Q/QRGZOdChAxRrYM9O1622LA4CqMgMvEkyNddd3S7p8dcZrOM6RS5/r44SUtesqhEEhIDeZXkJa9GfaRuk0c3FYwg0HWDmQ7pjizB5sBM8xCYXeiA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=oracle.com; dmarc=pass action=none header.from=oracle.com; dkim=pass header.d=oracle.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.onmicrosoft.com; s=selector2-oracle-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=B9eLiHX74bWzFmxZSby1pQPsglAyggQsU96uOm/DvWc=; b=frrMreqEbq7OL9JW+v3wQXwuk18qJS1DBSh+s9QFqXICLaiADu5HgzmdhHURnT+9RXPsKEtJYoVjiTVvIaG+uUSrdX1RxYH/0Nw7vxesjjI8q5hySWbBiaLYMomUMUHSxHvu7c1KEDjXv54Fz57Y8+msmnEtrHGTVPiAwW4HDiA= Received: from MW4PR10MB6608.namprd10.prod.outlook.com (2603:10b6:303:22e::8) by LV8PR10MB7966.namprd10.prod.outlook.com (2603:10b6:408:202::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7409.46; Wed, 17 Apr 2024 20:21:20 +0000 Received: from MW4PR10MB6608.namprd10.prod.outlook.com ([fe80::67a4:9544:7249:7751]) by MW4PR10MB6608.namprd10.prod.outlook.com ([fe80::67a4:9544:7249:7751%7]) with mapi id 15.20.7472.037; Wed, 17 Apr 2024 20:21:20 +0000 From: Nick Alcock To: binutils@sourceware.org Subject: [PATCH 13/22] libctf: make ctf_serialize() actually serialize Date: Wed, 17 Apr 2024 21:20:09 +0100 Message-ID: <20240417202018.34966-14-nick.alcock@oracle.com> X-Mailer: git-send-email 2.44.0.273.ge0bd14271f In-Reply-To: <20240417202018.34966-1-nick.alcock@oracle.com> References: <20240417202018.34966-1-nick.alcock@oracle.com> X-ClientProxiedBy: LO4P265CA0301.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:391::19) To MW4PR10MB6608.namprd10.prod.outlook.com (2603:10b6:303:22e::8) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: MW4PR10MB6608:EE_|LV8PR10MB7966:EE_ X-MS-Office365-Filtering-Correlation-Id: 952ccabc-b570-4358-836b-08dc5f1bf154 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: Thor3Ag8h+xKU5xW1kydSy4j6h5UQa5NNY5HsJ7tuFqS2smoJb+LDReMezw+uknjTo0nX3GcJ2UfY4vA9XiDCLKrhwoPTY35MypRBUi0VEwDElmr8/AnRSg5NJtojwiC2gk5x88aOZUyvBfiOnaQ1eQ4C4+JBpGbw+rwgrzTiEoRpe6N8EULseVVFbB1Ac5cv23oLetr3171caQf8CktWc8zStMrw2GYHoQXUTk5XKhMefgVRV3V3ikl9C40vb9oeTt7Wk4GIqiqzDjLLBHfQtQY2RnVWUwtZ8pJ7Ay3y+3P7VJ2zmb3wgGCQo6d3fRprRcZdgdA9G5e7QTnPC3CAkraR8t82z6b0LcHub8WHSlAEEVNga3G79GAGuvrV89LQpw8RjpYcWoJnHecrxa0wv8X3c0TElvx12I0zxfKACVsYRmDUPgwEc/GQol4owNj3pEooIdDF6882PugkBy+bJr+/I1YXZmKsTo0CIhOVT3JxHA3nQdwKYYWFE19euPZrhBeY/9PS/Cr8AeFlushU7dsTxQhnh1ofri6tcxy6oHJsml5CYxjQyQZkDYFCEnZYcGUnFZ/ZyFOlfSBjmalkUe7c4obMGyvy6I9S6Hs92fik67UGm81MK8UQtyWFpEvhT2XsK6LgU/XSH5GrsmR7NoB9K1OISAdWkoIbxNj0cM= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:MW4PR10MB6608.namprd10.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230031)(366007)(1800799015)(376005); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: B9kt+KVt4WXOeGuM6O7CVOHMCpw5MKddvdJv7rPlfqBmvHSQVDttBf4ly0rnkgBZqHeAJ7Yi47wsgb6EOVmlOTa6ckDUmilCPk8/41TC5GiO4OMOBwrVgQdFlNVKtND1ar14JYquV1+cvch/Vk5Z6ujp0ic0IMJJNXk37xdR9hPkDKqBS697g6hND6XDDU8MfStpcm8xIHD3usL9aRY1se9OPsQFXKxJaQQoXS6uxa0aUp2q2+xs6rpJKrdYJ8etx02ngxEbOYquVGVZXPqWVNsleviqpFUBIX69rsi5Kvt5uLT8fhWlV5npSHZiBAXRMuCeh/IBuKSFGjPt2Vqe+pUojoNtUvgq0p/stbOLV9POC8LP9iah+zkA8olKyiHLU9VUy+/wyJLAd2e7HFYY9k8t4Xposr7at8nY+vtpJd9vJIjdM71k+FI6pTCFzaIQdPq/SVbxRnd+S+i7liXkr+IWc6MGj3b3BIHezYq2yp+Hqn2+srshJeNI5JN/s8c9Nrj0qX9XnWqS4fT1dauxcLtJdYLyvTAq+R9xzpLQIcYOs+VufU7+jAEb9SWLh2JRzoaTSDiQi0vCVp2S7WT0X+viw7/sE/8NFLQEKppgaJQwHbUVGwgAEdZ+6MkrNl3IgfS0HOmWP82GD+zXFuWUXVwGdEI0sn7blpfPREBkTFIQ4sFMA5RA+J3D6gNZCU8zfrUTk8hrhk+q2nUkpAndG/3cgN84emVD9UK01HJw0UFMuCUInlJkFmivk7PKgpNZU2Yz8QW4w1ojxlxDka+NLYBiMO99BXfW07Q3+WanoBY7QxZAQ8aR7NayfcX1WrX1ZjB4uzLyIdoOe8fVGYtvwtUABpJZP20NWCusrU1qbA8/8cxkv4qZhW/xgQAxqgssyi7CGMs4vv8Hyw8TVgfjXFzmJHI6veEybl7UVQg7DMJXjC90QtDsX+Hwa9s0RaLX0e5qiWbq/65rokfn/Asn6H4L7cRscae3q6PdlN/rgTt8SnMXYFVEVf4XkdyTYhjoX7WyquVNq7dGfTLLZOb5I98gLWkiWZbXvFTY4NfOfhRtpe/0AMZ+vTwlSTci0O+Vr3AbwE8tYtGvN+uqqph/8FV+kO4CE1MOUGsjcmKh84Nt2cU+2kGeTwHHtcnJj1feDbs4UslwGPQe9SigfC9oTsc5N0PU8iWktp9cCz4QPHZsc1bNAxO2B6gX+CBTd4bDJ9GS0cJ8ShIk0MF4zTk1NfxrP2JEDWoyN3HqE4O2iD34P7n30B70DB6delVK05dgym8sSgk1iFyXMv3MgsuRAGs0ve6nOWwRu7XGiRBec9IWPP/VG0dvXPSAR/vWoCp3sTuqFoXR9/nGWgivdjap5RVzAbZKVfAGrUoqXonxWV0ZwAUiz1EgCEPTmYj2XmCBzxb6zk+bpeQeE0tguOQlhx6Thc4TF3CnUkMyG3Xy+hNvgGdLHdPj2AwFApCLlgsR+fhOp+pJoKseaeVJTuAhkQFSrKR4zugppkuY7Lk5D9HdXkmQ/buO5bvDJ8jHcs+4X2wTPbTbfeuvNTvRvVd2S7J1AUqIpmuxCwLz91+e+2zteCMtY2gai+ax2iXKFdk2tGQCohRs2YBW+6xRFZ9BkQ== X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0: OOdXrdKiR/863rkc9VsYalIIuA9nZT6P8UMPvnVvM2eUe4DtAeWWo8aa/kJzzmkhcWZDV8cZE5/CMNAW7z0Sfr7Rc4a21ZKQAOxU/OUPYp6HWntEl7gnqSozYUFhZ2+mU+JvBwDqefO5W981XlgSsNYyLy7Ed9ob3ICXPOTvuGun2CLWD2LbnqzqeWwnx/L57akr7NAcG+0ITLuftOu7ESNWTLmUEgs4D4VtMqpwIPNBk6hpUgWnHF4tbH5Ga5vxru5CZiT0LdrWXlgQ/Anqhf/8Il/Mj3LBHKDC3EojOjaPaEzuHkPuQ/NITZVPr05FwxYuCzto3dY7iHiSadGvqrWf5TAx28Z/f+gdpj8nCXot35J5aGJXAqK3Vae6Oe7aI7l34asjvjxpfDpkj2MvL9zEt9MR601JfmYdlBkFu3PBXNXelc5o759C5Siao6a3a5Ll+204WmUU6Cq+kB9WSEYG++HkBsFb1m8xPbcaElziAsbXBFsToVvHY9J3S4kDBT9hF41sJhwG8V3r0DWCKJRyh9Rx5mBcr5vxuXazC6FIMwR5jNdc0qx+lgXu+sLaMkkUr7/McGAu/TzS+qsMPDE7z0swI4feApye46IeMqM= X-OriginatorOrg: oracle.com X-MS-Exchange-CrossTenant-Network-Message-Id: 952ccabc-b570-4358-836b-08dc5f1bf154 X-MS-Exchange-CrossTenant-AuthSource: MW4PR10MB6608.namprd10.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 17 Apr 2024 20:21:19.9797 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 4e2c6054-71cb-48f1-bd6c-3a9705aca71b X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: LmwziI+7emboWO1VSdKIut02DgeFGYZidL6PSf0lxI4BtV2WD+EcyjmhXz4oH6eIrQpY32eDePfo0tOX/Ux5Bg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: LV8PR10MB7966 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.1011,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2024-04-17_17,2024-04-17_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 suspectscore=0 spamscore=0 mlxlogscore=999 phishscore=0 mlxscore=0 malwarescore=0 bulkscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2404010000 definitions=main-2404170143 X-Proofpoint-ORIG-GUID: 4NVgFM998r9NMiO-KXyyDwGwRBbD1JfT X-Proofpoint-GUID: 4NVgFM998r9NMiO-KXyyDwGwRBbD1JfT X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: binutils-bounces+patchwork=sourceware.org@sourceware.org ctf_serialize() evolved from the old ctf_update(), which mutated the in-memory CTF dict to make all the dynamic in-memory types into static, unchanging written-to-the-dict types (by deserializing and reserializing it): back in the days when you could only do type lookups on static types, this meant you could see all the types you added recently, at the small, small cost of making it impossible to change those older types ever again and inducing an amortized O(n^2) cost if you actually wanted to add references to types you added at arbitrary times to later types. It also reset things so that ctf_discard() would throw away only types you added after the most recent ctf_update() call. Some time ago this was all changed so that you could look up dynamic types just as easily as static types: ctf_update() changed so that only its visible side-effect of affecting ctf_discard() remained: the old ctf_update() was renamed to ctf_serialize(), made internal to libctf, and called from the various functions that wrote files out. ... but it was still working by serializing and deserializing the entire dict, swapping out its guts with the newly-serialized copy in an invasive and horrible fashion that coupled ctf_serialize() to almost every field in the ctf_dict_t. This is totally useless, and fixing it is easy: just rip all that code out and have ctf_serialize return a serialized representation, and let everything use that directly. This simplifies most of its callers significantly. (It also points up another bug: ctf_gzwrite() failed to call ctf_serialize() at all, so it would only ever work for a dict you just ctf_write_mem()ed yourself, just for its invisible side-effect of serializing the dict!) This lets us simplify away a bunch of internal-only open-side functionality for overriding the syn_ext_strtab and some just-added functionality for forcing in an existing atoms table, without loss of functionality, and lets us lift the restriction on reserializing a dict that was ctf_open()ed rather than being ctf_create()d: it's now perfectly OK to open a dict, modify it (except for adding members to existing structs, unions, or enums, which fails with -ECTF_RDONLY), and write it out again, just as one would expect. libctf/ * ctf-serialize.c (ctf_symtypetab_sect_sizes): Fix typos. (ctf_type_sect_size): Add static type sizes too. (ctf_serialize): Return the new dict rather than updating the existing dict. No longer fail for dicts with static types; copy them onto the start of the new types table. (ctf_gzwrite): Actually serialize before gzwriting. (ctf_write_mem): Improve forced (test-mode) endian-flipping: flip dicts even if they are too small to be compressed. Improve confusing variable naming. * ctf-archive.c (arc_write_one_ctf): Don't bother to call ctf_serialize: both the functions we call do so. * ctf-string.c (ctf_str_create_atoms): Drop serializing case (atoms arg). * ctf-open.c (ctf_simple_open): Call ctf_bufopen directly. (ctf_simple_open_internal): Delete. (ctf_bufopen_internal): Delete/rename to ctf_bufopen: no longer bother with syn_ext_strtab or forced atoms table, serialization no longer needs them. * ctf-create.c (ctf_create): Call ctf_bufopen directly. * ctf-impl.h (ctf_str_create_atoms): Drop atoms arg. (ctf_simple_open_internal): Delete. (ctf_bufopen_internal): Likewise. (ctf_serialize): Adjust. * testsuite/libctf-lookup/add-to-opened.c: Adjust now that this is supposed to work. --- libctf/ctf-archive.c | 7 +- libctf/ctf-create.c | 2 +- libctf/ctf-impl.h | 19 +- libctf/ctf-open.c | 39 +- libctf/ctf-serialize.c | 334 ++++++------------ libctf/ctf-string.c | 73 +--- .../testsuite/libctf-lookup/add-to-opened.c | 11 +- 7 files changed, 137 insertions(+), 348 deletions(-) diff --git a/libctf/ctf-archive.c b/libctf/ctf-archive.c index a88c6135e1a..3f12c0da85d 100644 --- a/libctf/ctf-archive.c +++ b/libctf/ctf-archive.c @@ -253,12 +253,12 @@ ctf_arc_write (const char *file, ctf_dict_t **ctf_dicts, size_t ctf_dict_cnt, return err; } -/* Write one CTF file out. Return the file position of the written file (or +/* Write one CTF dict out. Return the file position of the written file (or rather, of the file-size uint64_t that precedes it): negative return is a negative errno or ctf_errno value. On error, the file position may no longer be at the end of the file. */ static off_t -arc_write_one_ctf (ctf_dict_t * f, int fd, size_t threshold) +arc_write_one_ctf (ctf_dict_t *f, int fd, size_t threshold) { off_t off, end_off; uint64_t ctfsz = 0; @@ -266,9 +266,6 @@ arc_write_one_ctf (ctf_dict_t * f, int fd, size_t threshold) size_t ctfsz_len; int (*writefn) (ctf_dict_t * fp, int fd); - if (ctf_serialize (f) < 0) - return f->ctf_errno * -1; - if ((off = lseek (fd, 0, SEEK_CUR)) < 0) return errno * -1; diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c index 78fb0305c20..ee79e49794d 100644 --- a/libctf/ctf-create.c +++ b/libctf/ctf-create.c @@ -133,7 +133,7 @@ ctf_create (int *errp) cts.cts_size = sizeof (hdr); cts.cts_entsize = 1; - if ((fp = ctf_bufopen_internal (&cts, NULL, NULL, NULL, NULL, errp)) == NULL) + if ((fp = ctf_bufopen (&cts, NULL, NULL, errp)) == NULL) goto err; /* These hashes will have been initialized with a starting size of zero, diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h index 3eef232bea0..03e1a66416a 100644 --- a/libctf/ctf-impl.h +++ b/libctf/ctf-impl.h @@ -364,14 +364,7 @@ typedef struct ctf_dedup clients, who see it only as an opaque pointer. Modifications can therefore be made freely to this structure without regard to client versioning. The ctf_dict_t typedef appears in and declares a forward tag. - (A ctf_file_t typedef also appears there, for historical reasons.) - - NOTE: ctf_serialize requires that everything inside of ctf_dict either be an - immediate value, a pointer to dynamically allocated data *outside* of the - ctf_dict itself, a pointer to statically allocated data, or specially handled - in ctf_serialize. If you add a pointer to ctf_dict that points to something - within the ctf_dict itself, you must make corresponding changes to - ctf_serialize. */ + (A ctf_file_t typedef also appears there, for historical reasons.) */ struct ctf_dict { @@ -735,7 +728,7 @@ extern const char *ctf_strraw (ctf_dict_t *, uint32_t); extern const char *ctf_strraw_explicit (ctf_dict_t *, uint32_t, ctf_strs_t *); extern const char *ctf_strptr_validate (ctf_dict_t *, uint32_t); -extern int ctf_str_create_atoms (ctf_dict_t *, ctf_dynhash_t *atoms); +extern int ctf_str_create_atoms (ctf_dict_t *); extern void ctf_str_free_atoms (ctf_dict_t *); extern uint32_t ctf_str_add (ctf_dict_t *, const char *); extern uint32_t ctf_str_add_ref (ctf_dict_t *, const char *, uint32_t *ref); @@ -760,15 +753,7 @@ extern void *ctf_set_open_errno (int *, int); extern void ctf_flip_header (ctf_header_t *); extern int ctf_flip (ctf_dict_t *, ctf_header_t *, unsigned char *, int); -extern ctf_dict_t *ctf_simple_open_internal (const char *, size_t, const char *, - size_t, size_t, - const char *, size_t, - ctf_dynhash_t *, ctf_dynhash_t *, int *); -extern ctf_dict_t *ctf_bufopen_internal (const ctf_sect_t *, const ctf_sect_t *, - const ctf_sect_t *, ctf_dynhash_t *, - ctf_dynhash_t *, int *); extern int ctf_import_unref (ctf_dict_t *fp, ctf_dict_t *pfp); -extern int ctf_serialize (ctf_dict_t *); _libctf_malloc_ extern void *ctf_mmap (size_t length, size_t offset, int fd); diff --git a/libctf/ctf-open.c b/libctf/ctf-open.c index 6d7a276f2cd..9cbf07626cc 100644 --- a/libctf/ctf-open.c +++ b/libctf/ctf-open.c @@ -1233,9 +1233,8 @@ flip_types (ctf_dict_t *fp, void *start, size_t len, int to_foreign) return 0; } -/* Flip the endianness of BUF, given the offsets in the (already endian- - converted) CTH. If TO_FOREIGN is set, flip to foreign-endianness; if not, - flip away. +/* Flip the endianness of BUF, given the offsets in the (native-endianness) CTH. + If TO_FOREIGN is set, flip to foreign-endianness; if not, flip away. All of this stuff happens before the header is fully initialized, so the LCTF_*() macros cannot be used yet. Since we do not try to endian-convert v1 @@ -1287,21 +1286,6 @@ ctf_dict_t *ctf_simple_open (const char *ctfsect, size_t ctfsect_size, size_t symsect_entsize, const char *strsect, size_t strsect_size, int *errp) -{ - return ctf_simple_open_internal (ctfsect, ctfsect_size, symsect, symsect_size, - symsect_entsize, strsect, strsect_size, NULL, - NULL, errp); -} - -/* Open a CTF file, mocking up a suitable ctf_sect and overriding the external - strtab with a synthetic one. */ - -ctf_dict_t *ctf_simple_open_internal (const char *ctfsect, size_t ctfsect_size, - const char *symsect, size_t symsect_size, - size_t symsect_entsize, - const char *strsect, size_t strsect_size, - ctf_dynhash_t *syn_strtab, - ctf_dynhash_t *atoms, int *errp) { ctf_sect_t skeleton; @@ -1338,8 +1322,7 @@ ctf_dict_t *ctf_simple_open_internal (const char *ctfsect, size_t ctfsect_size, strsectp = &str_sect; } - return ctf_bufopen_internal (ctfsectp, symsectp, strsectp, syn_strtab, - atoms, errp); + return ctf_bufopen (ctfsectp, symsectp, strsectp, errp); } /* Decode the specified CTF buffer and optional symbol table, and create a new @@ -1350,16 +1333,6 @@ ctf_dict_t *ctf_simple_open_internal (const char *ctfsect, size_t ctfsect_size, ctf_dict_t * ctf_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect, const ctf_sect_t *strsect, int *errp) -{ - return ctf_bufopen_internal (ctfsect, symsect, strsect, NULL, NULL, errp); -} - -/* Like ctf_bufopen, but overriding the external strtab with a synthetic one. */ - -ctf_dict_t * -ctf_bufopen_internal (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect, - const ctf_sect_t *strsect, ctf_dynhash_t *syn_strtab, - ctf_dynhash_t *atoms, int *errp) { const ctf_preamble_t *pp; size_t hdrsz = sizeof (ctf_header_t); @@ -1370,8 +1343,7 @@ ctf_bufopen_internal (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect, libctf_init_debug(); - if ((ctfsect == NULL) || ((symsect != NULL) && - ((strsect == NULL) && syn_strtab == NULL))) + if ((ctfsect == NULL) || ((symsect != NULL) && (strsect == NULL))) return (ctf_set_open_errno (errp, EINVAL)); if (symsect != NULL && symsect->cts_entsize != sizeof (Elf32_Sym) && @@ -1623,7 +1595,7 @@ ctf_bufopen_internal (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect, fp->ctf_str[CTF_STRTAB_0].cts_strs = (const char *) fp->ctf_buf + hp->cth_stroff; fp->ctf_str[CTF_STRTAB_0].cts_len = hp->cth_strlen; - if (ctf_str_create_atoms (fp, atoms) < 0) + if (ctf_str_create_atoms (fp) < 0) { err = ENOMEM; goto bad; @@ -1669,7 +1641,6 @@ ctf_bufopen_internal (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect, fp->ctf_str[CTF_STRTAB_1].cts_strs = strsect->cts_data; fp->ctf_str[CTF_STRTAB_1].cts_len = strsect->cts_size; } - fp->ctf_syn_ext_strtab = syn_strtab; /* Dynamic state, for dynamic addition to this dict after loading. */ diff --git a/libctf/ctf-serialize.c b/libctf/ctf-serialize.c index 82e5b7d705b..2d1f014db28 100644 --- a/libctf/ctf-serialize.c +++ b/libctf/ctf-serialize.c @@ -470,9 +470,9 @@ ctf_symtypetab_sect_sizes (ctf_dict_t *fp, emit_symtypetab_state_t *s, filter out reported symbols from the variable section, and filter out all other symbols from the symtypetab sections. (If we are not linking, the symbols are sorted; if we are linking, don't bother sorting if we are not - filtering out reported symbols: this is almost certaily an ld -r and only + filtering out reported symbols: this is almost certainly an ld -r and only the linker is likely to consume these symtypetabs again. The linker - doesn't care what order the symtypetab entries is in, since it only + doesn't care what order the symtypetab entries are in, since it only iterates over symbols and does not use the ctf_lookup_by_symbol* API.) */ s->sort_syms = 1; @@ -718,8 +718,8 @@ symerr: /* Type section. */ -/* Iterate through the dynamic type definition list and compute the - size of the CTF type section. */ +/* Iterate through the static types and the dynamic type definition list and + compute the size of the CTF type section. */ static size_t ctf_type_sect_size (ctf_dict_t *fp) @@ -778,7 +778,7 @@ ctf_type_sect_size (ctf_dict_t *fp) } } - return type_size; + return type_size + fp->ctf_header->cth_stroff - fp->ctf_header->cth_typeoff; } /* Take a final lap through the dynamic type definition list and copy the @@ -933,30 +933,22 @@ ctf_sort_var (const void *one_, const void *two_, void *arg_) /* Overall serialization. */ -/* If the specified CTF dict is writable and has been modified, reload this dict - with the updated type definitions, ready for serialization. In order to make - this code and the rest of libctf as simple as possible, we perform updates by - taking the dynamic type definitions and creating an in-memory CTF dict - containing the definitions, and then call ctf_simple_open_internal() on it. - We perform one extra trick here for the benefit of callers and to keep our - code simple: ctf_simple_open_internal() will return a new ctf_dict_t, but we - want to keep the fp constant for the caller, so after - ctf_simple_open_internal() returns, we use memcpy to swap the interior of the - old and new ctf_dict_t's, and then free the old. +/* Emit a new CTF dict which is a serialized copy of this one: also reify + the string table and update all offsets in the current dict suitably. + (This simplifies ctf-string.c a little, at the cost of storing a second + copy of the strtab if this dict was originally read in via ctf_open.) - We do not currently support serializing a dict that has already been - serialized in the past: but all the tables support it except for the types - table. */ + Other aspects of the existing dict are unchanged, although some + static entries may be duplicated in the dynamic state (which should + have no effect on visible operation). */ -int -ctf_serialize (ctf_dict_t *fp) +static unsigned char * +ctf_serialize (ctf_dict_t *fp, size_t *bufsiz) { - ctf_dict_t ofp, *nfp; ctf_header_t hdr, *hdrp; ctf_dvdef_t *dvd; ctf_varent_t *dvarents; const ctf_strs_writable_t *strtab; - int err; int sym_functions = 0; unsigned char *t; @@ -969,13 +961,6 @@ ctf_serialize (ctf_dict_t *fp) emit_symtypetab_state_t symstate; memset (&symstate, 0, sizeof (emit_symtypetab_state_t)); - /* This isn't a very nice error code, but it's close enough: it's what you - get if you try to modify a type loaded out of a serialized dict, so - it makes at least a little sense that it's what you get if you try to - reserialize the dict again. */ - if (fp->ctf_stypes > 0) - return (ctf_set_errno (fp, ECTF_RDONLY)); - /* Fill in an initial CTF header. We will leave the label, object, and function sections empty and only output a header, type section, and string table. The type section begins at a 4-byte aligned @@ -993,7 +978,7 @@ ctf_serialize (ctf_dict_t *fp) /* Propagate all symbols in the symtypetabs into the dynamic state, so that we can put them back in the right order. Symbols already in the dynamic - state are left as they are. */ + state, likely due to repeated serialization, are left unchanged. */ do { ctf_next_t *it = NULL; @@ -1004,17 +989,17 @@ ctf_serialize (ctf_dict_t *fp) sym_functions)) != CTF_ERR) if ((ctf_add_funcobjt_sym_forced (fp, sym_functions, sym_name, sym)) < 0) if (ctf_errno (fp) != ECTF_DUPLICATE) - return -1; /* errno is set for us. */ + return NULL; /* errno is set for us. */ if (ctf_errno (fp) != ECTF_NEXT_END) - return -1; /* errno is set for us. */ + return NULL; /* errno is set for us. */ } while (sym_functions++ < 1); /* Figure out how big the symtypetabs are now. */ if (ctf_symtypetab_sect_sizes (fp, &symstate, &hdr, &objt_size, &func_size, &objtidx_size, &funcidx_size) < 0) - return -1; /* errno is set for us. */ + return NULL; /* errno is set for us. */ /* Propagate all vars into the dynamic state, so we can put them back later. Variables already in the dynamic state, likely due to repeated @@ -1026,7 +1011,7 @@ ctf_serialize (ctf_dict_t *fp) if (name != NULL && !ctf_dvd_lookup (fp, name)) if (ctf_add_variable_forced (fp, name, fp->ctf_vars[i].ctv_type) < 0) - return -1; /* errno is set for us. */ + return NULL; /* errno is set for us. */ } for (nvars = 0, dvd = ctf_list_next (&fp->ctf_dvdefs); @@ -1050,7 +1035,10 @@ ctf_serialize (ctf_dict_t *fp) buf_size = sizeof (ctf_header_t) + hdr.cth_stroff + hdr.cth_strlen; if ((buf = malloc (buf_size)) == NULL) - return (ctf_set_errno (fp, EAGAIN)); + { + ctf_set_errno (fp, EAGAIN); + return NULL; + } memcpy (buf, &hdr, sizeof (ctf_header_t)); t = (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_objtoff; @@ -1085,6 +1073,11 @@ ctf_serialize (ctf_dict_t *fp) assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_typeoff); + /* Copy in existing static types, then emit new dynamic types. */ + + memcpy (t, fp->ctf_buf + fp->ctf_header->cth_typeoff, + fp->ctf_header->cth_stroff - fp->ctf_header->cth_typeoff); + t += fp->ctf_header->cth_stroff - fp->ctf_header->cth_typeoff; ctf_emit_type_sect (fp, &t); assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_stroff); @@ -1111,136 +1104,15 @@ ctf_serialize (ctf_dict_t *fp) hdrp = (ctf_header_t *) buf; hdrp->cth_strlen = strtab->cts_len; buf_size += hdrp->cth_strlen; + *bufsiz = buf_size; - /* Finally, we are ready to ctf_simple_open() the new dict. If this is - successful, we then switch nfp and fp and free the old dict. */ - - if ((nfp = ctf_simple_open_internal ((char *) buf, buf_size, NULL, 0, - 0, NULL, 0, fp->ctf_syn_ext_strtab, - fp->ctf_str_atoms, &err)) == NULL) - { - free (buf); - return (ctf_set_errno (fp, err)); - } - - (void) ctf_setmodel (nfp, ctf_getmodel (fp)); - - nfp->ctf_parent = fp->ctf_parent; - nfp->ctf_parent_unreffed = fp->ctf_parent_unreffed; - nfp->ctf_refcnt = fp->ctf_refcnt; - if (nfp->ctf_dynbase == NULL) - nfp->ctf_dynbase = buf; /* Make sure buf is freed on close. */ - nfp->ctf_dthash = fp->ctf_dthash; - nfp->ctf_dtdefs = fp->ctf_dtdefs; - nfp->ctf_dvhash = fp->ctf_dvhash; - nfp->ctf_dvdefs = fp->ctf_dvdefs; - nfp->ctf_dtoldid = fp->ctf_dtoldid; - nfp->ctf_add_processing = fp->ctf_add_processing; - nfp->ctf_snapshots = fp->ctf_snapshots + 1; - nfp->ctf_specific = fp->ctf_specific; - nfp->ctf_nfuncidx = fp->ctf_nfuncidx; - nfp->ctf_nobjtidx = fp->ctf_nobjtidx; - nfp->ctf_objthash = fp->ctf_objthash; - nfp->ctf_funchash = fp->ctf_funchash; - nfp->ctf_dynsyms = fp->ctf_dynsyms; - nfp->ctf_ptrtab = fp->ctf_ptrtab; - nfp->ctf_pptrtab = fp->ctf_pptrtab; - nfp->ctf_typemax = fp->ctf_typemax; - nfp->ctf_stypes = fp->ctf_stypes; - nfp->ctf_dynsymidx = fp->ctf_dynsymidx; - nfp->ctf_dynsymmax = fp->ctf_dynsymmax; - nfp->ctf_ptrtab_len = fp->ctf_ptrtab_len; - nfp->ctf_pptrtab_len = fp->ctf_pptrtab_len; - nfp->ctf_link_inputs = fp->ctf_link_inputs; - nfp->ctf_link_outputs = fp->ctf_link_outputs; - nfp->ctf_errs_warnings = fp->ctf_errs_warnings; - nfp->ctf_funcidx_names = fp->ctf_funcidx_names; - nfp->ctf_objtidx_names = fp->ctf_objtidx_names; - nfp->ctf_funcidx_sxlate = fp->ctf_funcidx_sxlate; - nfp->ctf_objtidx_sxlate = fp->ctf_objtidx_sxlate; - nfp->ctf_str_prov_offset = fp->ctf_str_prov_offset; - nfp->ctf_syn_ext_strtab = fp->ctf_syn_ext_strtab; - nfp->ctf_pptrtab_typemax = fp->ctf_pptrtab_typemax; - nfp->ctf_in_flight_dynsyms = fp->ctf_in_flight_dynsyms; - nfp->ctf_link_in_cu_mapping = fp->ctf_link_in_cu_mapping; - nfp->ctf_link_out_cu_mapping = fp->ctf_link_out_cu_mapping; - nfp->ctf_link_type_mapping = fp->ctf_link_type_mapping; - nfp->ctf_link_memb_name_changer = fp->ctf_link_memb_name_changer; - nfp->ctf_link_memb_name_changer_arg = fp->ctf_link_memb_name_changer_arg; - nfp->ctf_link_variable_filter = fp->ctf_link_variable_filter; - nfp->ctf_link_variable_filter_arg = fp->ctf_link_variable_filter_arg; - nfp->ctf_symsect_little_endian = fp->ctf_symsect_little_endian; - nfp->ctf_link_flags = fp->ctf_link_flags; - nfp->ctf_dedup_atoms = fp->ctf_dedup_atoms; - nfp->ctf_dedup_atoms_alloc = fp->ctf_dedup_atoms_alloc; - memcpy (&nfp->ctf_dedup, &fp->ctf_dedup, sizeof (fp->ctf_dedup)); - - nfp->ctf_snapshot_lu = fp->ctf_snapshots; - - memcpy (&nfp->ctf_lookups, fp->ctf_lookups, sizeof (fp->ctf_lookups)); - nfp->ctf_structs = fp->ctf_structs; - nfp->ctf_unions = fp->ctf_unions; - nfp->ctf_enums = fp->ctf_enums; - nfp->ctf_names = fp->ctf_names; - - fp->ctf_dthash = NULL; - ctf_str_free_atoms (nfp); - nfp->ctf_str_atoms = fp->ctf_str_atoms; - nfp->ctf_prov_strtab = fp->ctf_prov_strtab; - nfp->ctf_dynstrtab = fp->ctf_dynstrtab; - nfp->ctf_str_movable_refs = fp->ctf_str_movable_refs; - fp->ctf_str_atoms = NULL; - fp->ctf_prov_strtab = NULL; - fp->ctf_dynstrtab = NULL; - fp->ctf_str_movable_refs = NULL; - memset (&fp->ctf_dtdefs, 0, sizeof (ctf_list_t)); - memset (&fp->ctf_errs_warnings, 0, sizeof (ctf_list_t)); - fp->ctf_add_processing = NULL; - fp->ctf_ptrtab = NULL; - fp->ctf_pptrtab = NULL; - fp->ctf_funcidx_names = NULL; - fp->ctf_objtidx_names = NULL; - fp->ctf_funcidx_sxlate = NULL; - fp->ctf_objtidx_sxlate = NULL; - fp->ctf_objthash = NULL; - fp->ctf_funchash = NULL; - fp->ctf_dynsyms = NULL; - fp->ctf_dynsymidx = NULL; - fp->ctf_link_inputs = NULL; - fp->ctf_link_outputs = NULL; - fp->ctf_syn_ext_strtab = NULL; - fp->ctf_link_in_cu_mapping = NULL; - fp->ctf_link_out_cu_mapping = NULL; - fp->ctf_link_type_mapping = NULL; - fp->ctf_dedup_atoms = NULL; - fp->ctf_dedup_atoms_alloc = NULL; - fp->ctf_parent_unreffed = 1; - - fp->ctf_dvhash = NULL; - memset (&fp->ctf_dvdefs, 0, sizeof (ctf_list_t)); - memset (fp->ctf_lookups, 0, sizeof (fp->ctf_lookups)); - memset (&fp->ctf_in_flight_dynsyms, 0, sizeof (fp->ctf_in_flight_dynsyms)); - memset (&fp->ctf_dedup, 0, sizeof (fp->ctf_dedup)); - fp->ctf_structs = NULL; - fp->ctf_unions = NULL; - fp->ctf_enums = NULL; - fp->ctf_names = NULL; - - memcpy (&ofp, fp, sizeof (ctf_dict_t)); - memcpy (fp, nfp, sizeof (ctf_dict_t)); - memcpy (nfp, &ofp, sizeof (ctf_dict_t)); - - nfp->ctf_refcnt = 1; /* Force nfp to be freed. */ - ctf_dict_close (nfp); - - return 0; + return buf; oom: - free (buf); - return (ctf_set_errno (fp, EAGAIN)); + ctf_set_errno (fp, EAGAIN); err: free (buf); - return -1; /* errno is set for us. */ + return NULL; /* errno is set for us. */ } /* File writing. */ @@ -1255,30 +1127,27 @@ err: int ctf_gzwrite (ctf_dict_t *fp, gzFile fd) { - const unsigned char *buf; - ssize_t resid; - ssize_t len; + unsigned char *buf; + unsigned char *p; + size_t bufsiz; + size_t len, written = 0; - resid = sizeof (ctf_header_t); - buf = (unsigned char *) fp->ctf_header; - while (resid != 0) + if ((buf = ctf_serialize (fp, &bufsiz)) == NULL) + return -1; /* errno is set for us. */ + + p = buf; + while (written < bufsiz) { - if ((len = gzwrite (fd, buf, resid)) <= 0) - return (ctf_set_errno (fp, errno)); - resid -= len; - buf += len; - } - - resid = fp->ctf_size; - buf = fp->ctf_buf; - while (resid != 0) - { - if ((len = gzwrite (fd, buf, resid)) <= 0) - return (ctf_set_errno (fp, errno)); - resid -= len; - buf += len; + if ((len = gzwrite (fd, p, bufsiz - written)) <= 0) + { + free (buf); + return (ctf_set_errno (fp, errno)); + } + written += len; + p += len; } + free (buf); return 0; } @@ -1288,88 +1157,95 @@ ctf_gzwrite (ctf_dict_t *fp, gzFile fd) unsigned char * ctf_write_mem (ctf_dict_t *fp, size_t *size, size_t threshold) { - unsigned char *buf; + unsigned char *rawbuf; + unsigned char *buf = NULL; unsigned char *bp; - ctf_header_t *hp; - unsigned char *flipped, *src; - ssize_t header_len = sizeof (ctf_header_t); - ssize_t compress_len; + ctf_header_t *rawhp, *hp; + unsigned char *src; + size_t rawbufsiz; + size_t alloc_len = 0; + int uncompressed = 0; int flip_endian; - int uncompressed; int rc; flip_endian = getenv ("LIBCTF_WRITE_FOREIGN_ENDIAN") != NULL; - uncompressed = (fp->ctf_size < threshold); - if (ctf_serialize (fp) < 0) + if ((rawbuf = ctf_serialize (fp, &rawbufsiz)) == NULL) return NULL; /* errno is set for us. */ - compress_len = compressBound (fp->ctf_size); - if (fp->ctf_size < threshold) - compress_len = fp->ctf_size; - if ((buf = malloc (compress_len - + sizeof (struct ctf_header))) == NULL) + if (!ctf_assert (fp, rawbufsiz >= sizeof (ctf_header_t))) + goto err; + + if (rawbufsiz >= threshold) + alloc_len = compressBound (rawbufsiz - sizeof (ctf_header_t)) + + sizeof (ctf_header_t); + + /* Trivial operation if the buffer is incompressible or too small to bother + compressing, and we're not doing a forced write-time flip. */ + + if (rawbufsiz < threshold || rawbufsiz < alloc_len) + { + alloc_len = rawbufsiz; + uncompressed = 1; + } + + if (!flip_endian && uncompressed) + { + *size = rawbufsiz; + return rawbuf; + } + + if ((buf = malloc (alloc_len)) == NULL) { ctf_set_errno (fp, ENOMEM); ctf_err_warn (fp, 0, 0, _("ctf_write_mem: cannot allocate %li bytes"), - (unsigned long) (compress_len + sizeof (struct ctf_header))); - return NULL; + (unsigned long) (alloc_len)); + goto err; } + rawhp = (ctf_header_t *) rawbuf; hp = (ctf_header_t *) buf; - memcpy (hp, fp->ctf_header, header_len); - bp = buf + sizeof (struct ctf_header); - *size = sizeof (struct ctf_header); + memcpy (hp, rawbuf, sizeof (ctf_header_t)); + bp = buf + sizeof (ctf_header_t); + *size = sizeof (ctf_header_t); - if (uncompressed) - hp->cth_flags &= ~CTF_F_COMPRESS; - else + if (!uncompressed) hp->cth_flags |= CTF_F_COMPRESS; - src = fp->ctf_buf; - flipped = NULL; + src = rawbuf + sizeof (ctf_header_t); if (flip_endian) { - if ((flipped = malloc (fp->ctf_size)) == NULL) - { - ctf_set_errno (fp, ENOMEM); - ctf_err_warn (fp, 0, 0, _("ctf_write_mem: cannot allocate %li bytes"), - (unsigned long) (fp->ctf_size + sizeof (struct ctf_header))); - return NULL; - } ctf_flip_header (hp); - memcpy (flipped, fp->ctf_buf, fp->ctf_size); - if (ctf_flip (fp, fp->ctf_header, flipped, 1) < 0) - { - free (buf); - free (flipped); - return NULL; /* errno is set for us. */ - } - src = flipped; + if (ctf_flip (fp, rawhp, src, 1) < 0) + goto err; /* errno is set for us. */ } - if (uncompressed) - { - memcpy (bp, src, fp->ctf_size); - *size += fp->ctf_size; - } - else + if (!uncompressed) { + size_t compress_len = alloc_len - sizeof (ctf_header_t); + if ((rc = compress (bp, (uLongf *) &compress_len, - src, fp->ctf_size)) != Z_OK) + src, rawbufsiz - sizeof (ctf_header_t))) != Z_OK) { ctf_set_errno (fp, ECTF_COMPRESS); ctf_err_warn (fp, 0, 0, _("zlib deflate err: %s"), zError (rc)); - free (buf); - return NULL; + goto err; } *size += compress_len; } + else + { + memcpy (bp, src, rawbufsiz - sizeof (ctf_header_t)); + *size += rawbufsiz - sizeof (ctf_header_t); + } - free (flipped); - + free (rawbuf); return buf; +err: + free (buf); + free (rawbuf); + return NULL; } /* Compress the specified CTF data stream and write it to the specified file diff --git a/libctf/ctf-string.c b/libctf/ctf-string.c index ccf36498eb9..465b2c88ac8 100644 --- a/libctf/ctf-string.c +++ b/libctf/ctf-string.c @@ -143,15 +143,9 @@ ctf_str_free_atom (void *a) calls to ctf_str_add_external to populate external strtab entries, since these are often not quite the same as what appears in any external strtab, and the external strtab is often huge and best not aggressively - pulled in.) - - Alternatively, if passed, populate atoms from the passed-in table, but do - not propagate their flags or refs: they are all non-freeable and - non-movable. (This is used when serializing a dict: this entire atoms - table will be thrown away shortly, so it is important that we not create - any new strings.) */ + pulled in.) */ int -ctf_str_create_atoms (ctf_dict_t *fp, ctf_dynhash_t *atoms) +ctf_str_create_atoms (ctf_dict_t *fp) { size_t i; @@ -178,61 +172,26 @@ ctf_str_create_atoms (ctf_dict_t *fp, ctf_dynhash_t *atoms) if (errno == ENOMEM) goto oom_str_add; - /* Serializing. We have existing strings in an existing atoms table with - possibly-live pointers to them which must be used unchanged. Import - them into this atoms table. */ + /* Pull in all the strings in the strtab as new atoms. The provisional + strtab must be empty at this point, so there is no need to populate + atoms from it as well. Types in this subset are frozen and readonly, + so the refs list and movable refs list need not be populated. */ - if (atoms) + for (i = 0; i < fp->ctf_str[CTF_STRTAB_0].cts_len; + i += strlen (&fp->ctf_str[CTF_STRTAB_0].cts_strs[i]) + 1) { - ctf_next_t *it = NULL; - void *k, *v; - int err; + ctf_str_atom_t *atom; - while ((err = ctf_dynhash_next (atoms, &it, &k, &v)) == 0) - { - ctf_str_atom_t *existing = v; - ctf_str_atom_t *atom; + if (fp->ctf_str[CTF_STRTAB_0].cts_strs[i] == 0) + continue; - if (existing->csa_str[0] == 0) - continue; + atom = ctf_str_add_ref_internal (fp, &fp->ctf_str[CTF_STRTAB_0].cts_strs[i], + 0, 0); - if ((atom = malloc (sizeof (struct ctf_str_atom))) == NULL) - goto oom_str_add; - memcpy (atom, existing, sizeof (struct ctf_str_atom)); - memset (&atom->csa_refs, 0, sizeof(ctf_list_t)); - atom->csa_flags = 0; + if (!atom) + goto oom_str_add; - if (ctf_dynhash_insert (fp->ctf_str_atoms, atom->csa_str, atom) < 0) - { - free (atom); - goto oom_str_add; - } - } - } - else - { - /* Not serializing. Pull in all the strings in the strtab as new - atoms. The provisional strtab must be empty at this point, so - there is no need to populate atoms from it as well. Types in this - subset are frozen and readonly, so the refs list and movable refs - list need not be populated. */ - - for (i = 0; i < fp->ctf_str[CTF_STRTAB_0].cts_len; - i += strlen (&fp->ctf_str[CTF_STRTAB_0].cts_strs[i]) + 1) - { - ctf_str_atom_t *atom; - - if (fp->ctf_str[CTF_STRTAB_0].cts_strs[i] == 0) - continue; - - atom = ctf_str_add_ref_internal (fp, &fp->ctf_str[CTF_STRTAB_0].cts_strs[i], - 0, 0); - - if (!atom) - goto oom_str_add; - - atom->csa_offset = i; - } + atom->csa_offset = i; } return 0; diff --git a/libctf/testsuite/libctf-lookup/add-to-opened.c b/libctf/testsuite/libctf-lookup/add-to-opened.c index dc2e1f55b99..96629afe1aa 100644 --- a/libctf/testsuite/libctf-lookup/add-to-opened.c +++ b/libctf/testsuite/libctf-lookup/add-to-opened.c @@ -118,11 +118,9 @@ main (int argc, char *argv[]) if (ctf_errno (fp) != ECTF_RDONLY) fprintf (stderr, "unexpected error %s attempting to set array in readonly portion\n", ctf_errmsg (ctf_errno (fp))); - if ((ctf_written = ctf_write_mem (fp, &size, 4096)) != NULL) - fprintf (stderr, "Writeout unexpectedly succeeded: %s\n", ctf_errmsg (ctf_errno (fp))); - - if (ctf_errno (fp) != ECTF_RDONLY) - fprintf (stderr, "unexpected error %s trying to write out previously serialized dict\n", ctf_errmsg (ctf_errno (fp))); + if ((ctf_written = ctf_write_mem (fp, &size, 4096)) == NULL) + fprintf (stderr, "Re-writeout unexpectedly failed: %s\n", ctf_errmsg (ctf_errno (fp))); + free (ctf_written); /* Finally, make sure we can add new types, and look them up again. */ @@ -138,6 +136,9 @@ main (int argc, char *argv[]) if (ctf_type_reference (fp, ptrtype) != type) fprintf (stderr, "Look up of newly-added type in serialized dict yields ID %lx, expected %lx\n", ctf_type_reference (fp, ptrtype), type); + ctf_dict_close (fp); + ctf_close (ctf); + printf ("All done.\n"); return 0;