Rebindability

If the binder processes duplicate sections, it keeps only the first one. This feature is particularly important when rebinding. You must include the changed parts first and the old program object second. This is how you replace the changed sections.

The binder can process each object module separately so that you only need to recompile and rebind the modules that you have modified. You do not need to recompile or include the object module for any unchanged modules.

When the binder replaces a named section, it also replaces all of its parts (named or unnamed). If a section does not have the name you want, you can change it with the #pragma csect directive or with the CSECT compiler option. Unnamed parts typically come from the following:

You should name all sections if you want to rebind. If a section is unnamed (has a private name) and you attempt to replace it on a rebind, the unnamed section is not replaced by the updated but corresponding unnamed section. Instead, the binder keeps both the old and new unnamed sections, causing the program module to grow in size. All references to functions that are defined by both the old section and the new section are resolved first to functions in the new section. The program may run correctly, but you will get warnings about duplicate function definitions at bind time. These duplicates will never go away on future rebinds because you cannot replace or delete unnamed sections. You will also accumulate dead code in the duplicate functions which can never be accessed. This is why it is important to name all sections if you want to rebind your code.

Example: Suppose that our DLL consists of two compile units, cu3.c and cu4.c, that are bound using the JCL in Figure 1:
/* file: cu3.c */
/* compile with: LONGNAME RENT EXPORTALL*/
#pragma csect(code,"CODE3")
func3(void) { return 4; }
int int3 = 3;
/* file: cu4.c */
/* compile with: LONGNAME RENT EXPORTALL */
#pragma csect(code,"CODE4")
func4(void) { return 4; }
int int4 = 4;
Figure 1. JCL to bind cu3.c and cu4.c
//BIND1    EXEC CBCB,
//         BPARM='CALL,MAP,DYNAM(DLL)',
//         OUTFILE='USERID.PLAN9.LOADE,DISP=SHR'
//INOBJ    DD DISP=SHR,DSN=USERID.PLAN9.OBJ
//SYSLIN   DD *
 INCLUDE INOBJ(CU3)
 INCLUDE INOBJ(CU4)
 ENTRY CEESTART
 NAME BADEXE(R)
/*
Later, you discover that func3 is in error and should return 3. Change the source code in cu3.c and recompile. Rebind as follows:
//BIND1    EXEC CBCB,
//         BPARM='LIST(ALL),CALL,XREF,LET,MAP,DYNAM(DLL)',
//         OUTFILE='USERID.PLAN9.LOADE,DISP=SHR'
//INOBJ    DD DISP=SHR,DSN=USERID.PLAN9.OBJ
//INPOBJ   DD DISP=SHR,DSN=USERID.PLAN9.LOADE
//SYSLIN   DD *
 INCLUDE INOBJ(CU3)
 INCLUDE SYSLMOD(BADEXE)
 ENTRY CEESTART
 NAME GOODEXE(R)
/*
The input event log in the binder listing shows:
IEW2322I 1220  1    INCLUDE INOBJ(CU3)
IEW2308I 1112 SECTION CODE3 HAS BEEN MERGED.
IEW2308I 1112 SECTION int3 HAS BEEN MERGED.
IEW2322I 1220  2    INCLUDE INPOBJ(BADEXE)
IEW2308I 1112 SECTION CODE4 HAS BEEN MERGED.
IEW2308I 1112 SECTION int4 HAS BEEN MERGED.
IEW2308I 1112 SECTION CEESTART HAS BEEN MERGED.
IEW2308I 1112 SECTION CEESG003 HAS BEEN MERGED.
IEW2308I 1112 SECTION CEEBETBL HAS BEEN MERGED.
IEW2308I 1112 SECTION CEEBPUBT HAS BEEN MERGED.
IEW2308I 1112 SECTION CEEBTRM HAS BEEN MERGED.
IEW2308I 1112 SECTION CEEBLLST HAS BEEN MERGED.
IEW2308I 1112 SECTION CEEBINT HAS BEEN MERGED.
IEW2308I 1112 SECTION CEETGTFN HAS BEEN MERGED.
IEW2308I 1112 SECTION CEETLOC HAS BEEN MERGED.
IEW2322I 1220  3    ENTRY CEESTART
IEW2322I 1220  4    NAME GOODEXE(R)

BADEXE defines sections int3, CODE3, int4, and CODE4. If the binder sees duplicate sections, it uses the first one that it reads. Since CU3 defines sections CODE3 and int3, and is included before BADEXE, both sections are replaced by the newer ones in CU3 when program object GOODEXE is created.

DLL considerations

Any IMPORT control statements used in the original bind must also be input to the re-bind, unless the dynamic resolution information is available via an INCLUDE statement.