1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23#ifdef SHLIB
24#include "shlib.h"
25#endif /* SHLIB */
26/*
27 * This file contains the routines that deal with literal 'C' string sections.
28 * A string in this section must beable to me moved freely with respect to other
29 * strings or data.  This means relocation must not reach outside the string and
30 * things like: "abc"[i+20] can't be in this type of section.  Also strings
31 * like: "foo\0bar" can not be in this type of section.
32 */
33#include <stdlib.h>
34#if !(defined(KLD) && defined(__STATIC__))
35#include <stdio.h>
36#include <limits.h>
37#include <mach/mach.h>
38#else /* defined(KLD) && defined(__STATIC__) */
39#include <mach/mach.h>
40#include <mach/kern_return.h>
41#define CHAR_MAX 0xff
42#endif /* !(defined(KLD) && defined(__STATIC__)) */
43#include <stdarg.h>
44#include <string.h>
45#include "stuff/openstep_mach.h"
46#include <mach-o/loader.h>
47#include "stuff/bool.h"
48#include "stuff/bytesex.h"
49
50#include "ld.h"
51#include "live_refs.h"
52#include "objects.h"
53#include "sections.h"
54#include "cstring_literals.h"
55#include "pass2.h"
56#include "hash_string.h"
57#include "symbols.h"
58
59/*
60 * cstring_merge() merges cstring literals from the specified section in the
61 * current object file (cur_obj).  When redo_live is FALSE it allocates a fine
62 * relocation map and sets the fine_relocs field in the section_map to it (as
63 * well as the count).  When redo_live is TRUE it re-merges only the live
64 * cstrings based on the live bit in the previouly allocated fine_relocs.
65 */
66__private_extern__
67void
68cstring_merge(
69struct cstring_data *data,
70struct merged_section *ms,
71struct section *s,
72struct section_map *section_map,
73enum bool redo_live)
74{
75    unsigned long ncstrings, i;
76    char *cstrings, *p;
77    struct fine_reloc *fine_relocs;
78
79	if(s->size == 0){
80	    if(redo_live == FALSE){
81		section_map->fine_relocs = NULL;
82		section_map->nfine_relocs = 0;
83	    }
84	    return;
85	}
86	/*
87	 * Count the number of strings so the size of the fine relocation
88	 * structures can be allocated.
89	 */
90	ncstrings = 0;
91	cstrings = cur_obj->obj_addr + s->offset;
92	if(*(cstrings + s->size - 1) != '\0'){
93	    error_with_cur_obj("literal C string section (%.16s,%.16s) does "
94			       "not end with a '\\0'", s->segname, s->sectname);
95	    return;
96	}
97	for(p = cstrings; p < cstrings + s->size; p += strlen(p) + 1)
98	    ncstrings++;
99#ifdef DEBUG
100	if(redo_live == FALSE){
101	    data->nfiles++;
102	    data->nbytes += s->size;
103	    data->ninput_strings += ncstrings;
104	}
105#endif /* DEBUG */
106
107	/*
108	 * We will be called the first time with redo_live == FALSE and will
109	 * just merge the cstrings from the input file and create the
110	 * fine_relocs.
111	 */
112	if(redo_live == FALSE){
113	    fine_relocs = allocate(ncstrings * sizeof(struct fine_reloc));
114	    memset(fine_relocs, '\0', ncstrings * sizeof(struct fine_reloc));
115
116	    /*
117	     * lookup and enter each C string in the section and record the
118	     * offsets in the input file and in the output file.
119	     */
120	    p = cstrings;
121	    for(i = 0; i < ncstrings; i++){
122		fine_relocs[i].input_offset = p - cstrings;
123		fine_relocs[i].output_offset = lookup_cstring(p, data, ms);
124		p += strlen(p) + 1;
125	    }
126	    section_map->fine_relocs = fine_relocs;
127	    section_map->nfine_relocs = ncstrings;
128	}
129	else{
130	    /*
131	     * redo_live == TRUE and this is being called a second time after
132	     * all the cstrings were previouly merged when -dead_strip is
133	     * specified.  So now we walk the fine_relocs and only re-merge the
134	     * live strings.
135	     */
136	    fine_relocs = section_map->fine_relocs;
137	    ncstrings = section_map->nfine_relocs;
138	    p = cstrings;
139	    for(i = 0; i < ncstrings; i++){
140		if(fine_relocs[i].live == TRUE){
141		    fine_relocs[i].output_offset = lookup_cstring(p, data, ms);
142		}
143		else{
144		    fine_relocs[i].output_offset = 0;
145		}
146		p += strlen(p) + 1;
147	    }
148	}
149}
150
151/*
152 * cstring_order() enters cstring literals from the order_file from the merged
153 * section structure.  Since this is called before any call to cstring_merge
154 * and it enters the strings in the order of the file it causes the section
155 * to be ordered.
156 */
157__private_extern__
158void
159cstring_order(
160struct cstring_data *data,
161struct merged_section *ms)
162{
163#ifndef RLD
164    unsigned long i, line_number, line_length, max_line_length, output_offset;
165    char *buffer;
166    kern_return_t r;
167    struct cstring_order_line *cstring_order_lines;
168
169	/*
170	 * Parse the load order file by changing '\n' to '\0'.  Also check for
171	 * '\0 in the file and flag them as errors.  Also determine the maximum
172	 * line length of the file for the needed buffer to allocate for
173	 * character translation.
174	 */
175	line_number = 1;
176	line_length = 1;
177	max_line_length = 1;
178	for(i = 0; i < ms->order_size; i++){
179	    if(ms->order_addr[i] == '\0'){
180		fatal("format error in -sectorder file: %s line %lu character "
181		      "possition %lu for section (%.16s,%.16s) (illegal null "
182		      "character \'\\0\' found)", ms->order_filename,
183		      line_number, line_length, ms->s.segname, ms->s.sectname);
184	    }
185	    if(ms->order_addr[i] == '\n'){
186		ms->order_addr[i] = '\0';
187		if(line_length > max_line_length)
188		    max_line_length = line_length;
189		line_number++;
190		line_length = 1;
191	    }
192	    else
193		line_length++;
194	}
195
196	/*
197	 * Allocate the buffer to translate the order file lines' escape
198	 * characters into real characters.
199	 */
200	buffer = allocate(max_line_length + 1);
201
202	/*
203	 * If -dead_strip is specified allocate the needed structures so that
204	 * the order of the live cstrings can be recreated later by
205	 * cstring_reset_live().
206	 */
207	cstring_order_lines = NULL;
208	if(dead_strip == TRUE){
209	    data->cstring_load_order_data =
210		allocate(sizeof(struct cstring_load_order_data));
211	    cstring_order_lines = allocate(sizeof(struct cstring_order_line) *
212					   (line_number - 1));
213	    data->cstring_load_order_data->order_line_buffer =
214		buffer;
215	    data->cstring_load_order_data->cstring_order_lines =
216		cstring_order_lines;
217	    data->cstring_load_order_data->ncstring_order_lines =
218		(line_number - 1);
219	}
220
221	/*
222	 * Process each line in the order file by translating all escape
223	 * characters and then entering the cstring using lookup_cstring().
224	 * If -dead_strip is specified save away the starting character index
225	 * of each order line and the output offset.
226	 */
227	line_number = 1;
228	for(i = 0; i < ms->order_size; i++){
229	    if(dead_strip == TRUE)
230		cstring_order_lines[line_number - 1].character_index = i;
231
232	    get_cstring_from_sectorder(ms, &i, buffer, line_number, 1);
233	    output_offset = lookup_cstring(buffer, data, ms);
234
235	    if(dead_strip == TRUE)
236		cstring_order_lines[line_number - 1].output_offset =
237		    output_offset;
238
239	    line_number++;
240	}
241
242	/*
243	 * If -dead_strip is not specified free up the memory for the line
244	 * buffer and the load order file.  If -dead_strip is specified these
245	 * will be free'ed up in cstring_reset_live().
246	 */
247	if(dead_strip == FALSE){
248
249	    /* deallocate the line buffer */
250	    free(buffer);
251
252	    /*
253	     * Deallocate the memory for the load order file now that it is
254	     * nolonger needed (since the memory has been written on it is
255	     * always deallocated so it won't get written to the swap file
256	     * unnecessarily).
257	     */
258	    if((r = vm_deallocate(mach_task_self(), (vm_address_t)
259		ms->order_addr, ms->order_size)) != KERN_SUCCESS)
260		mach_fatal(r, "can't vm_deallocate() memory for -sectorder "
261			   "file: %s for section (%.16s,%.16s)",
262			   ms->order_filename, ms->s.segname,
263			   ms->s.sectname);
264	    ms->order_addr = NULL;
265	}
266#endif /* !defined(RLD) */
267}
268
269/*
270 * cstring_reset_live() is called when -dead_strip is specified after all the
271 * literals from the input objects are merged.  It clears out the cstring_data
272 * so the live cstrings can be re-merged (by later calling cstring_merge() with
273 * redo_live == TRUE.  In here we first merge in the live cstrings from the
274 * order file if any.
275 */
276__private_extern__
277void
278cstring_reset_live(
279struct cstring_data *data,
280struct merged_section *ms)
281{
282#ifndef RLD
283    unsigned long i, ncstring_order_lines, character_index, line_number;
284    char *buffer;
285    struct cstring_order_line *cstring_order_lines;
286    enum bool live;
287    kern_return_t r;
288
289	/* reset the merge section size back to zero */
290	ms->s.size = 0;
291
292	/* clear out the previously merged data */
293	cstring_free(data);
294
295	/*
296	 * If this merged section has an order file we need to re-merged only
297	 * the live cstrings from that order file.
298	 */
299	if(ms->order_filename != NULL){
300	    buffer = data->cstring_load_order_data->order_line_buffer;
301	    cstring_order_lines =
302		data->cstring_load_order_data->cstring_order_lines;
303	    ncstring_order_lines =
304		data->cstring_load_order_data->ncstring_order_lines;
305	    for(i = 0; i < ncstring_order_lines; i++){
306		/*
307		 * Figure out if this cstring order line's output_index is live
308		 * and if so re-merge the cstring literal.
309		 */
310		live = is_literal_output_offset_live(
311			ms, cstring_order_lines[i].output_offset);
312		line_number = i + 1;
313		if(live){
314		    character_index = cstring_order_lines[i].character_index;
315		    get_cstring_from_sectorder(ms, &character_index, buffer,
316					       line_number, 1);
317		    (void)lookup_cstring(buffer, data, ms);
318		}
319		else{
320		    if(sectorder_detail == TRUE)
321			warning("specification of string in -sectorder file: "
322				"%s on line %lu for section (%.16s,%.16s) not "
323				"used (dead stripped)", ms->order_filename,
324				line_number, ms->s.segname, ms->s.sectname);
325		}
326	    }
327
328	    /* deallocate the various data structures no longer needed */
329	    free(data->cstring_load_order_data->order_line_buffer);
330	    free(data->cstring_load_order_data->cstring_order_lines);
331	    free(data->cstring_load_order_data);
332	    data->cstring_load_order_data = NULL;
333
334	    /*
335	     * Deallocate the memory for the load order file now that it is
336	     * nolonger needed (since the memory has been written on it is
337	     * allways deallocated so it won't get written to the swap file
338	     * unnecessarily).
339	     */
340	    if((r = vm_deallocate(mach_task_self(), (vm_address_t)
341		ms->order_addr, ms->order_size)) != KERN_SUCCESS)
342		mach_fatal(r, "can't vm_deallocate() memory for -sectorder "
343			   "file: %s for section (%.16s,%.16s)",
344			   ms->order_filename, ms->s.segname,
345			   ms->s.sectname);
346	    ms->order_addr = NULL;
347	}
348#endif /* !defined(RLD) */
349}
350
351/*
352 * get_cstring_from_sectorder() parses a cstring from a order file for the
353 * specified merged_section, ms, starting from the index, *index the order file
354 * must have had its newlines changed to '\0's previouly.  It places the parsed
355 * cstring in the specified buffer, buffer and advances the index over the
356 * cstring it parsed.  line_number and char_pos are used for printing error
357 * messages and refer the line_number and character possition the index is at.
358 */
359__private_extern__
360void
361get_cstring_from_sectorder(
362struct merged_section *ms,
363unsigned long *index,
364char *buffer,
365unsigned long line_number,
366unsigned long char_pos)
367{
368#ifndef RLD
369    unsigned long i, j, k, char_value;
370    char octal[4], hex[9];
371
372	j = 0;
373	/*
374	 * See that this is not the end of a line in the order file.
375	 */
376	for(i = *index; i < ms->order_size && ms->order_addr[i] != '\0'; i++){
377	    /*
378	     * See if this character the start of an escape sequence.
379	     */
380	    if(ms->order_addr[i] == '\\'){
381		if(i + 1 >= ms->order_size || ms->order_addr[i + 1] == '\0')
382		    fatal("format error in -sectorder file: %s line %lu "
383			  "character possition %lu for section (%.16s,"
384			  "%.16s) (\'\\\' at the end of the line)",
385			  ms->order_filename, line_number, char_pos,
386			  ms->s.segname, ms->s.sectname);
387		/* move past the '\\' */
388		i++;
389		char_pos++;
390		if(ms->order_addr[i] >= '0' && ms->order_addr[i] <= '7'){
391		    /* 1, 2 or 3 octal digits */
392		    k = 0;
393		    octal[k++] = ms->order_addr[i];
394		    char_pos++;
395		    if(i+1 < ms->order_size &&
396		       ms->order_addr[i+1] >= '0' &&
397		       ms->order_addr[i+1] <= '7'){
398			octal[k++] = ms->order_addr[++i];
399			char_pos++;
400		    }
401		    if(i+1 < ms->order_size &&
402		       ms->order_addr[i+1] >= '0' &&
403		       ms->order_addr[i+1] <= '7'){
404			octal[k++] = ms->order_addr[++i];
405			char_pos++;
406		    }
407		    octal[k] = '\0';
408		    char_value = strtol(octal, NULL, 8);
409		    if(char_value > CHAR_MAX){
410			error("format error in -sectorder file: %s line %lu "
411			      "for section (%.16s,%.16s) (escape sequence"
412			      " ending at character possition %lu out of "
413			      "range for character)", ms->order_filename,
414			      line_number, ms->s.segname, ms->s.sectname,
415			      char_pos - 1);
416		    }
417		    buffer[j++] = (char)char_value;
418		}
419		else{
420		    switch(ms->order_addr[i]){
421		    case 'n':
422			buffer[j++] = '\n';
423			char_pos++;
424			break;
425		    case 't':
426			buffer[j++] = '\t';
427			char_pos++;
428			break;
429		    case 'v':
430			buffer[j++] = '\v';
431			char_pos++;
432			break;
433		    case 'b':
434			buffer[j++] = '\b';
435			char_pos++;
436			break;
437		    case 'r':
438			buffer[j++] = '\r';
439			char_pos++;
440			break;
441		    case 'f':
442			buffer[j++] = '\f';
443			char_pos++;
444			break;
445		    case 'a':
446			buffer[j++] = '\a';
447			char_pos++;
448			break;
449		    case '\\':
450			buffer[j++] = '\\';
451			char_pos++;
452			break;
453		    case '\?':
454			buffer[j++] = '\?';
455			char_pos++;
456			break;
457		    case '\'':
458			buffer[j++] = '\'';
459			char_pos++;
460			break;
461		    case '\"':
462			buffer[j++] = '\"';
463			char_pos++;
464			break;
465		    case 'x':
466			/* hex digits */
467			k = 0;
468			while(i+1 < ms->order_size &&
469			      ((ms->order_addr[i+1] >= '0' &&
470				ms->order_addr[i+1] <= '9') ||
471			       (ms->order_addr[i+1] >= 'a' &&
472				ms->order_addr[i+1] <= 'f') ||
473			       (ms->order_addr[i+1] >= 'A' &&
474				ms->order_addr[i+1] <= 'F')) ){
475			    if(k <= 8)
476				hex[k++] = ms->order_addr[++i];
477			    else
478				++i;
479			    char_pos++;
480			}
481			if(k > 8){
482			    error("format error in -sectorder file: %s line"
483				  " %lu for section (%.16s,%.16s) (hex "
484				  "escape ending at character possition "
485				  "%lu out of range)", ms->order_filename,
486				  line_number, ms->s.segname,
487				  ms->s.sectname, char_pos);
488			    break;
489			}
490			hex[k] = '\0';
491			char_value = strtol(hex, NULL, 16);
492			if(char_value > CHAR_MAX){
493			    error("format error in -sectorder file: %s line"
494				  " %lu for section (%.16s,%.16s) (escape "
495				  "sequence ending at character possition "
496				  "%lu out of range for character)",
497				  ms->order_filename, line_number,
498				  ms->s.segname, ms->s.sectname, char_pos);
499			}
500			buffer[j++] = (char)char_value;
501			char_pos++;
502			break;
503		    default:
504			error("format error in -sectorder file: %s line %lu "
505			      "for section (%.16s,%.16s) (unknown escape "
506			      "sequence ending at character possition %lu)",
507			      ms->order_filename, line_number,
508			      ms->s.segname, ms->s.sectname, char_pos);
509			buffer[j++] = ms->order_addr[i];
510			char_pos++;
511			break;
512		    }
513		}
514	    }
515	    /*
516	     * This character is not the start of an escape sequence so take
517	     * it as it is.
518	     */
519	    else{
520		buffer[j] = ms->order_addr[i];
521		char_pos++;
522		j++;
523	    }
524	}
525	buffer[j] = '\0';
526	*index = i;
527#endif /* !defined(RLD) */
528}
529
530/*
531 * lookup_cstring() looks up the cstring passed to it in the cstring_data
532 * passed to it and returns the offset the cstring will have in the output
533 * file.  It creates the hash table as needed and the blocks to store the
534 * strings and attaches them to the cstring_data passed to it.  The total
535 * size of the section is accumulated in ms->s.size which is the merged
536 * section for this literal section.  The string is aligned to the alignment
537 * in the merged section (ms->s.align).
538 */
539__private_extern__
540unsigned long
541lookup_cstring(
542char *cstring,
543struct cstring_data *data,
544struct merged_section *ms)
545{
546    unsigned long hashval, len, cstring_len;
547    struct cstring_bucket *bp;
548    struct cstring_block **p, *cstring_block;
549
550	if(data->hashtable == NULL){
551	    data->hashtable = allocate(sizeof(struct cstring_bucket *) *
552				       CSTRING_HASHSIZE);
553	    memset(data->hashtable, '\0', sizeof(struct cstring_bucket *) *
554					  CSTRING_HASHSIZE);
555	}
556#if defined(DEBUG) && defined(PROBE_COUNT)
557	    data->nprobes++;
558#endif
559	hashval = hash_string(cstring, NULL) % CSTRING_HASHSIZE;
560	for(bp = data->hashtable[hashval]; bp; bp = bp->next){
561	    if(strcmp(cstring, bp->cstring) == 0)
562		return(bp->offset);
563#if defined(DEBUG) && defined(PROBE_COUNT)
564	    data->nprobes++;
565#endif
566	}
567
568	cstring_len = strlen(cstring) + 1;
569	len = rnd(cstring_len, 1 << ms->s.align);
570	bp = allocate(sizeof(struct cstring_bucket));
571	for(p = &(data->cstring_blocks); *p ; p = &(cstring_block->next)){
572	    cstring_block = *p;
573	    if(cstring_block->full)
574		continue;
575	    if(len > cstring_block->size - cstring_block->used){
576		cstring_block->full = TRUE;
577		continue;
578	    }
579	    strcpy(cstring_block->cstrings + cstring_block->used, cstring);
580	    memset(cstring_block->cstrings + cstring_block->used + cstring_len,
581		   '\0', len - cstring_len);
582	    bp->cstring = cstring_block->cstrings + cstring_block->used;
583	    cstring_block->used += len;
584	    bp->offset = ms->s.size;
585	    bp->next = data->hashtable[hashval];
586	    data->hashtable[hashval] = bp;
587	    ms->s.size += len;
588#ifdef DEBUG
589	    data->noutput_strings++;
590#endif /* DEBUG */
591	    return(bp->offset);
592	}
593	*p = allocate(sizeof(struct cstring_block));
594	cstring_block = *p;
595	cstring_block->size = (len > host_pagesize ? len : host_pagesize);
596	cstring_block->used = len;
597	cstring_block->full = (len == cstring_block->size ? TRUE : FALSE);
598	cstring_block->next = NULL;
599	cstring_block->cstrings = allocate(cstring_block->size);
600	strcpy(cstring_block->cstrings, cstring);
601	memset(cstring_block->cstrings + cstring_len, '\0', len - cstring_len);
602	bp->cstring = cstring_block->cstrings;
603	bp->offset = ms->s.size;
604	bp->next = data->hashtable[hashval];
605	data->hashtable[hashval] = bp;
606	ms->s.size += len;
607#ifdef DEBUG
608	data->noutput_strings++;
609#endif /* DEBUG */
610	return(bp->offset);
611}
612
613/*
614 * cstring_output() copies the cstrings for the data passed to it into the
615 * output file's buffer.  The pointer to the merged section passed to it is
616 * used to tell where in the output file this section goes.  Then this routine
617 * called cstring_free() to free() up all space used by this data block except
618 * the data block itself.
619 */
620__private_extern__
621void
622cstring_output(
623struct cstring_data *data,
624struct merged_section *ms)
625{
626    unsigned long offset;
627    struct cstring_block **p, *cstring_block;
628
629	/*
630	 * Copy the blocks into the output file.
631	 */
632	offset = ms->s.offset;
633	for(p = &(data->cstring_blocks); *p ;){
634	    cstring_block = *p;
635	    memcpy(output_addr + offset,
636		   cstring_block->cstrings,
637		   cstring_block->used);
638	    offset += cstring_block->used;
639	    p = &(cstring_block->next);
640	}
641#ifndef RLD
642	output_flush(ms->s.offset, offset - ms->s.offset);
643#endif /* !defined(RLD) */
644	cstring_free(data);
645}
646
647/*
648 * cstring_free() free()'s up all space used by this cstring_data block except
649 * the data block itself.
650 */
651__private_extern__
652void
653cstring_free(
654struct cstring_data *data)
655{
656    unsigned long i;
657    struct cstring_bucket *bp, *next_bp;
658    struct cstring_block *cstring_block, *next_cstring_block;
659
660	/*
661	 * Free all data for this block.
662	 */
663	if(data->hashtable != NULL){
664	    for(i = 0; i < CSTRING_HASHSIZE; i++){
665		for(bp = data->hashtable[i]; bp; ){
666		    next_bp = bp->next;
667		    free(bp);
668		    bp = next_bp;
669		}
670	    }
671	    free(data->hashtable);
672	    data->hashtable = NULL;
673	}
674	for(cstring_block = data->cstring_blocks; cstring_block ;){
675	    next_cstring_block = cstring_block->next;
676	    free(cstring_block->cstrings);
677	    free(cstring_block);
678	    cstring_block = next_cstring_block;
679	}
680	data->cstring_blocks = NULL;
681}
682
683#ifdef DEBUG
684/*
685 * print_cstring_data() prints a cstring_data.  Used for debugging.
686 */
687__private_extern__
688void
689print_cstring_data(
690struct cstring_data *data,
691char *indent)
692{
693    char *s;
694    struct cstring_block **p, *cstring_block;
695/*
696    unsigned long i;
697    struct cstring_bucket *bp;
698*/
699
700	print("%sC string data at 0x%x\n", indent, (unsigned int)data);
701	if(data == NULL)
702	    return;
703	print("%s    hashtable 0x%x\n", indent,(unsigned int)(data->hashtable));
704/*
705	if(data->hashtable != NULL){
706	    for(i = 0; i < CSTRING_HASHSIZE; i++){
707		print("%s    %-3d [0x%x]\n", indent, i, data->hashtable[i]);
708		for(bp = data->hashtable[i]; bp; bp = bp->next){
709		    print("%s\tcstring %s\n", indent, bp->cstring);
710		    print("%s\toffset  %lu\n", indent, bp->offset);
711		    print("%s\tnext    0x%x\n", indent, bp->next);
712		}
713	    }
714	}
715*/
716	print("%s   cstring_blocks 0x%x\n", indent,
717	      (unsigned int)(data->cstring_blocks));
718	for(p = &(data->cstring_blocks); *p ; p = &(cstring_block->next)){
719	    cstring_block = *p;
720	    print("%s\tsize %lu\n", indent, cstring_block->size);
721	    print("%s\tused %lu\n", indent, cstring_block->used);
722	    if(cstring_block->full)
723		print("%s\tfull TRUE\n", indent);
724	    else
725		print("%s\tfull FALSE\n", indent);
726	    print("%s\tnext 0x%x\n", indent,
727		  (unsigned int)(cstring_block->next));
728	    print("%s\tcstrings\n", indent);
729	    for(s = cstring_block->cstrings;
730	        s < cstring_block->cstrings + cstring_block->used;
731	        s += strlen(s) + 1){
732		print("%s\t    %s\n", indent, s);
733	    }
734	}
735}
736
737/*
738 * cstring_data_stats() prints the cstring_data stats.  Used for tuning.
739 */
740__private_extern__
741void
742cstring_data_stats(
743struct cstring_data *data,
744struct merged_section *ms)
745{
746	if(data == NULL)
747	    return;
748	print("literal cstring section (%.16s,%.16s) contains:\n",
749	      ms->s.segname, ms->s.sectname);
750	print("    %u bytes of merged strings\n", ms->s.size);
751	print("    from %lu files and %lu total bytes from those "
752	      "files\n", data->nfiles, data->nbytes);
753	print("    average number of bytes per file %g\n",
754	      (double)((double)data->nbytes / (double)(data->nfiles)));
755	print("    %lu merged strings\n", data->noutput_strings);
756	print("    from %lu files and %lu total strings from those "
757	      "files\n", data->nfiles, data->ninput_strings);
758	print("    average number of strings per file %g\n",
759	      (double)((double)data->ninput_strings / (double)(data->nfiles)));
760	if(data->nprobes != 0){
761	    print("    number of hash probes %lu\n", data->nprobes);
762	    print("    average number of hash probes %g\n",
763	    (double)((double)(data->nprobes) / (double)(data->ninput_strings)));
764	}
765}
766#endif /* DEBUG */
767