xref: /illumos-gate/usr/src/lib/README.mapfiles (revision e4f5a11d4a234623168c1558fcdf4341e11769e1)
1#
2# CDDL HEADER START
3#
4# The contents of this file are subject to the terms of the
5# Common Development and Distribution License (the "License").
6# You may not use this file except in compliance with the License.
7#
8# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9# or http://www.opensolaris.org/os/licensing.
10# See the License for the specific language governing permissions
11# and limitations under the License.
12#
13# When distributing Covered Code, include this CDDL HEADER in each
14# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15# If applicable, add the following below this CDDL HEADER, with the
16# fields enclosed by brackets "[]" replaced with your own identifying
17# information: Portions Copyright [yyyy] [name of copyright owner]
18#
19# CDDL HEADER END
20#
21#
22# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
23#
24
25Mapfiles and versioning in ON
26=============================
27
281.0 Objective of this README
29
30This README describes the engineering practices of creating and updating
31visible library interfaces.  It describes various kinds of actions that
32typically occur as libraries are evolved, and shows how interface
33specifications are affected or updated in accordance.  It tells you what
34you must do as a shared library developer if you:
35
36	1. Make interface additions to an existing library
37		- add a Public interface
38		- add a Private interface
39	2. Update an interface in an existing library
40		- remove an existing interface
41		- promote a Private interface to Public
42		- scope a Private interface to local
43		- move an interface from one library to another
44		- copy interfaces which are part of the standard to a new or
45		  existing library
46	3. Introduce a new library
47		- source directory hierarchy
48		- creation of the "mapfile-vers" file
49		- Makefiles
50	4. Make an entire library obsolete before end-of-life
51		- introduce SUNWobsolete to the "mapfile-vers" file
52
53-------------------------------------------------------------------------------
54
552.0 What's a mapfile?
56
57Mapfiles are used to tell the link-editor ("ld") all sorts of things about
58how to generate an executable file or a shared object from a collection of
59relocatable objects, such as generated by a compiler.  For all the gory
60details, see the Solaris Linker and Libraries Guide, which can be found
61under http://docs.sun.com.
62
63There are two versions of the mapfile language accepted by the link-editor.
64Version 1 derives from AT&T System V Release 4 Unix. Version 2 is a newer
65syntax specific to Solaris. All mapfiles in the OSnet (ON consolidation) are
66required to use version 2 syntax. Note that every mapfile using version 2
67syntax must start with the line:
68
69        $mapfile_version 2
70
71Here, we are only concerned with specifying externally-visible interfaces
72for shared libraries (shared objects) and with specifying their versions
73for ABI (Application Binary Interface) purposes.  For these purposes, we
74only need to deal with a subset of the mapfile language.
75
76There should be a "mapfile-vers" file associated with every shared library
77and it should reside in the common source directory for that library, most
78often in a "common" directory.  This is the usual layout of a library's
79top-level directory (usr/src/lib/libwombat):
80	Makefile       amd64/         i386/          sparcv9/
81	Makefile.com   common/        sparc/
82
83The "common" directory contains the source files and other common files
84for the library:
85	bat.c              libwombat_impl.h   mapfile-vers       wom.c
86	libwombat.h        llib-lwombat       util.c             wombat.c
87
88The mapfile's name is, by convention, "mapfile-vers" because it is used
89for only two purposes: to specify externally-visible interface names while
90suppressing visibility of all other names, and to specify their respective
91unique version names.
92
93-------------------------------------------------------------------------------
94
953.0 Contents of mapfile-vers
96
97The structure of mapfile-vers is best explained by an example
98(the license notification and copyright notice is omitted here
99for brevity):
100
101$mapfile_version 2
102
103SYMBOL_VERSION SUNW_1.2 {	# update to libwombat, Solaris 10
104    global:
105	wb_readv;
106	wb_stat;
107	wb_writev;
108} SUNW_1.1;
109
110SYMBOL_VERSION SUNW_1.1 {	# first release of libwombat, Solaris 9
111    global:
112	wb_read;
113	wb_write;
114};
115
116SYMBOL_VERSION SUNWprivate {	# private libwombat symbols
117    global:
118	wb_add;
119	wb_delete;
120	wb_search;
121    local:
122	*;
123};
124
125The SUNW_1.* names are the Public version names for the library.
126There should be at most one version name for each release of Solaris,
127with the minor number incremented by one over the previous version.
128
129If no update to the Public-visible names in the library is made
130in a given Solaris release, no new version name should be generated
131for that release.  If multiple updates are made to the library at
132different points in the development of a given release of Solaris,
133only one version should be used for the entire release.
134
135So, for example, if an update to libwombat is made in Solaris 11,
136you would add "SUNW_1.3" at the start of the mapfile:
137
138SYMBOL_VERSION SUNW_1.3 {	# update to libwombat, Solaris 11
139    global:
140	wb_lseek;
141} SUNW_1.2;
142
143Each version must inherit all symbols from its preceding version,
144specified at the ending "}" for each version.  SUNW_1.1 does not
145inherit any symbols.  SUNWprivate, if present, stands alone.
146
147The two lines in SUNWprivate:
148    local:
149	*;
150ensure that no symbols other than those listed in the mapfile are
151visible to clients of the library.  If there is no SUNWprivate,
152these two lines should appear in SUNW_1.1.
153
154For maintainability, the list of names in each version block should
155be sorted in dictionary order (sort -d).  Please comply.
156
157The version 2 mapfile language supports a simple mechanism for conditional
158input, in which lines in the mapfile apply only to a specific platform or
159ELFCLASS (32/64-bit). This mechanism works very much like the #if/#endif
160feature of the C preprocessor. For instance, the following mapfile declares
161a version SUNW_1.1 that always exports a symbol foo, and also exports
162the symbol bar on 32-bit sparc platforms:
163
164$mapfile_version
165SYMBOL_VERSION SUNW_1.1 {
166        foo;
167$if _sparc && _ELF32
168	bar;
169$endif
170};
171
172Conditional input can be used if there are ISA-specific library interfaces
173not common to all instances of the library. It is the preferred method for
174expressing platform specific items, as long as the differences are simple
175(which is almost always the case).  For example, see libproc, or, if you
176are masochistic, libc or libnsl.
177
178In addition to conditional input, there is a second heavier weight mechanism
179for expressing ISA-specific differences. In addition to the common mapfile:
180	common/mapfile-vers
181some libraries may have ISA-specific supplemental mapfiles, one in each
182of the ISA directories:
183	amd64/mapfile-vers
184	i386/mapfile-vers
185	sparc/mapfile-vers
186	sparcv9/mapfile-vers
187The ISA-specific mapfiles look like the common mapfile, except that only
188the ISA-specific names appear.  The version names are the same as those
189in the common mapfile, but only non-empty version instances are present
190and no inheritance specification is present. The link-editor reads the
191information from the common and ISA-specific mapfiles and merges them
192in memory into a single description used to create the resulting object.
193
194ISA-specific mapfiles were used with the version 1 mapfile language, which
195lacked conditional input. Their use is rare now, as conditional input is
196generally preferred. However, it is important to use conditional input
197carefully, or the resulting mapfile can be extremly difficult to read.
198
199-------------------------------------------------------------------------------
200
2014.0 Making interface additions to an existing library
202
2034.1 Adding a Public interface
204
205The first engineer to update the existing mapfile-vers file in a release needs
206to identify the current highest version name and properly increment the minor
207version number by 1 to be the new version name.  If this is the first Public
208interface in the shared object, a new SUNW_1.1 version name must be introduced.
209
210The major revision number is incremented whenever an incompatible change is
211made to an interface.  This could be the case if an API changes so dramatically
212as to invalidate dependencies.  This rarely occurs in practice.  It also
213requires changing the suffix of the shared object from, say, .so.1 to .so.2
214and introducing code to continue to ship the .so.1 version of the library.
215
216The minor revision number is incremented whenever one or more new interfaces
217is added to a library.  Note that the minor number is not incremented on every
218putback that makes an interface addition to the library.  Rather, it is
219incremented at most once per (external to Sun) release of the library.
220
2214.2 Adding a Private interface
222
223Private interfaces are the non-ABI interfaces of the library.  Unlike
224introducing a Public interface, a new entry is simply added to the
225SUNWprivate version.  No minor number increment is necessary.
226
227If this interface happens to be the first Private interface introduced
228into the library, the SUNWprivate version must be created (no major.minor
229version numbers).  It inherits nothing and nothing inherits from it.
230
231If the library already has Private interfaces, they may have numbered version
232names like SUNWprivate_m.n (due to errors of the past).  If so, just use the
233highest numbered private version name to version the new interface.  There
234is no need to introduce a new private version name.  Be careful not to use
235a lower numbered private version name; doing so can cause runtime errors
236(as opposed to load time errors) when running an application with older
237versions of the library.
238
239There are libraries in the OSnet consolidation that contain only private
240interfaces. In such libraries, the SUNWprivate_m.n may be incremented
241to ensure that the programs that depend on them are built and delivered as a
242integrated unit. A notable example of this is libld.so (usr/src/cmd/sgs/libld),
243which contains the implementation of the link-editor, the public interface to
244which is provided by the ld command. When making a modification to the interface
245of such a library, you should follow the convention already in place.
246
2474.3 Adding new public interfaces in an update release
248
249Adding new public interfaces in an update release requires careful
250coordination with the next marketing release currently under development.
251Multiple updates ship during the period before the next marketing release
252ships, and since it is generally impossible to know the full set of new
253interfaces in the next marketing release until late in its development
254(after multiple updates have shipped) it must be assumed that not all
255interfaces added to the next marketing release will be added to an update.
256
257Consequently, the new version number for an update cannot be a minor
258increment, but must be a micro increment.  For example, if Release N
259has version number SUNW_1.3 and Release N+1 will have SUNW_1.4, then
260interfaces added to an update of Release N must have micro numbers such
261as SUNW_1.3.1, SUNW_1.3.2, etc.  (note that the micro number is not
262directly tied to the update number: SUNW_1.3.1 may appear in Update 2).
263The micro versions form an inheritance chain that is inserted between
264two successive minor versions.  For example, the mapfile-vers file for
265minor release "N+1" to reflect its inclusion of micro releases will
266look like the following:
267
268$mapfile_version 2
269
270SYMBOL_VERSION SUNW_1.4 {	# release N+1
271    global:
272	...
273} SUNW_1.3.2;
274
275SYMBOL_VERSION SUNW_1.3.2 {	# micro release 2 (e.g., release NU3)
276    global:
277	...
278} SUNW_1.3.1;
279
280SYMBOL_VERSION SUNW_1.3.1 {	# micro release 1 (e.g., release NU2)
281    global:
282	...
283} SUNW_1.3;
284
285SYMBOL_VERSION SUNW_1.3 {	# release N
286    global:
287	...
288} SUNW_1.2;
289
290SYMBOL_VERSION SUNW_1.2 {	# release N-1
291    global:
292	...
293} SUNW_1.1;
294
295SYMBOL_VERSION SUNW_1.1 {	# first release
296    global:
297	...
298};
299
300SYMBOL_VERSION SUNW_private {	# same in all releases
301    global:
302	...
303    local:
304	*;
305};
306
307The corresponding update/patch mapfile-vers file will be identical
308except for the exclusion of SUNW_1.4.
309
310Those interfaces which are only present in Release N+1 are always put
311into the next minor version set, SUNW_1.4.
312
313Thus when adding a new public interface to an update, both the mapfiles
314of the update release and next marketing release must be modified to be
315consistent.  The update versions should not be added to the marketing
316release until the putback to the update release has occurred, to avoid
317timing problems with the update releases (it's all too easy for projects
318to slip out of updates, or to change ordering).
319
320-------------------------------------------------------------------------------
321
3225.0 How to update an interface in an existing library
323
3245.1 Removing an existing interface
325
3265.1.1 Moving a Public interface
327
328No Public interfaces should ever be removed from any mapfile.
329
330To move an interface from one library to (say) libc, the code has to be
331deleted from the library and added to libc, then the mapfile for the
332library has to have the interface's entry changed from:
333	getfoobar;
334to:
335	getfoobar       { TYPE = FUNCTION; FILTER = libc.so.1 };
336See, for example, libnsl's common/mapfile-vers file.
337
338Follow the rules for adding a new interface for the necessary changes
339to libc's mapfile to accommodate the moved interface.  In particular,
340the new interface must be added to the current highest libc version.
341
342To move an entire library into libc, look at what has already been done
343for libthread, libaio, and librt.
344
3455.1.2 Removing a Private interface
346
347Deletion of Private interfaces is allowed, but caution should be taken;
348it should first be established that the interface is not being used.
349To remove a Private interface, simply delete the corresponding entry
350for that symbol from the mapfile's SUNWprivate section.
351
352Do not forget to delete these Public or Private interfaces from the library's
353header files as well as from the code that implements the interfaces.
354
3555.2 Promoting a Private interface to Public
356
357This is similar to what's done when adding a Public interface.  Promoting an
358existing Private interface to a Public one only requires a change to the
359existing interface definition.  Private interfaces have the symbol version name
360"SUNWprivate" associated with them.  To make the interface a Public one, the
361interface must be put into a set associated with the current Public release
362level of the library.
363
364As an example, if we were modifying libwombat.so.1 and its version in the
365last release of Solaris was SUNW_1.23, any new ABI introduced in the next
366release would be put into a version called SUNW_1.24.  Therefore, whether
367you wish to promote an existing Private interface to Public, or to introduce
368a new Public interface, this (next successive minor numbered version level)
369would be the version that it would be associated with.
370
3715.3 Scoping a Private interface local
372
373Any interfaces not present in the mapfile-vers file will be scoped local
374due to the presence of the
375    local:
376	*;
377lines discussed earlier. This ensures that such interfaces will not be visible
378outside the library.  To move an interface from Private to local scope, simply
379remove the Private interface from the mapfile-vers file and the header file
380to prevent it from being exported.  This may require moving the Private
381interface into a library-private header file.  Scope reduction of Public
382interfaces is not allowed without specific ARC review and approval.
383
384For the interface to be used in more than one file within the library, it
385should be in a header file that can be included by each file in the library
386that uses the interface.  For example:
387
388	#include "libprivate.h"
389
3905.4 How to copy interfaces which are part of a standard to a new or existing
391    library
392
393SYSVABI and SISCD are reserved version names for interfaces listed in the
394System V Interface Definition and the Sparc Compliance Definition.  Avoid using
395these version names when copying the implementation of standard interfaces to
396another library.  Instead, use SUNW_1.1 for a new library, and SUNW_m.n for
397an existing library (where m.n is the next release version; i.e., if the
398last version was SUNW_1.18, then you should version the interfaces with
399SUNW_1.19).
400
401-------------------------------------------------------------------------------
402
4036.0 Introducing a new library
404
4056.1 Directories
406
407The normal discipline for introducing a new library in OS/Net is to create a
408new subdirectory of /usr/src/lib.  The interface definition discipline is to
409create a common/mapfile-vers file for the new library.  If we were introducing
410a new foo library, libfoo, we'd create /usr/src/lib/libfoo containing:
411	Makefile       amd64/         i386/          sparcv9/
412	Makefile.com   common/        sparc/
413The common subdirectory would contain the normal source files plus the
414mapfile-vers file.  See usr/src/lib/README.Makefiles for directions on
415how to organize the Makefiles.
416
4176.2 The mapfile
418
419The new common/mapfile-vers file would contain:
420
421$mapfile_version 2
422
423SYMBOL_VERSION SUNW_1.1 {	# first release of libfoo
424    global:
425	...
426};
427
428SYMBOL_VERSION SUNWprivate {
429    global:
430	...
431    local:
432	*;
433};
434
435If there are no Public interfaces, the SUNW_1.1 section would be omitted.
436If there are no Private interfaces, the SUNWprivate section would be
437omitted and the two lines:
438    local:
439	*;
440would be moved into SUNW_1.1
441
442To decide which interfaces are Public (part of the ABI) and which are Private
443(unstable interfaces not intended to be used by third party applications or
444unbundled products), the heuristic which works to a first approximation is
445that if it has a man page then it's Public.  Also, it is really the ARC case
446for the new interfaces that prescribes which interfaces are Public and
447which are not (hence, which interfaces have man pages and which do not).
448
449For maintainability, the list of names in each version block should
450be sorted in dictionary order (sort -d).  Please comply.
451
452-------------------------------------------------------------------------------
453
4547.0 Make an entire library obsolete
455
4567.1 Introduce SUNWobsolete version
457
458Use this version name not for specific interfaces but for marking an entire
459library as obsolete.  The existing public/private version names are left
460unchanged, but a new SUNWobsolete version is created with no symbols in it.
461This becomes a tag by which the obsolescence of the library can be recognized.
462There is no numbering of this version name.
463
464$mapfile_version 2
465
466SYMBOL_VERSION SUNWobsolete {
467    global:
468	SUNWobsolete;	# This is the only way to do it.
469} SUNW_1.2;
470
471SYMBOL_VERSION SUNW_1.2 {
472...
473
474-------------------------------------------------------------------------------
475
4768.0 Documentation
477
478For further information, please refer to the following documents:
479
480	"Solaris Linker and Libraries Guide", http://docs.sun.com
481	/shared/ON/general_docs/scoping-rules.fm.ps
482
483For information on the now-obsolete spec files, used in Solaris releases
4847 through 10, see:
485	/shared/ON/general_docs/README.spec
486	/shared/ON/general_docs/libspec-rules.ps
487	/shared/ON/general_docs/spectrans/*
488